Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Виртуозное владение IARом
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
LeoLabs
Предлагаю открыть новую тему, помогающую овладеть всеми хитростями IARa всем начинающим. Также предлагаю вносить свои идеи, фенечки и тонкости, какими пользуетесь при написании проги на ИАРе.

И первый вопрос: - я организовал массив в СИ, с начальным адресом 0х100 и длиной 256 - чар : "__no_init unsigned char MyBuffer [256]@0x100;" - идея сделать кольцевой буффер, для простой работой с указателями (простой инкремент младшего байта указателя), с ним я работаю как в СИ, так и в ассемблере. ?? - как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом?
standpoint
Цитата(LeoLabs @ May 18 2005, 08:09)
Предлагаю открыть новую тему, помогающую овладеть всеми хитростями IARa всем начинающим. Также предлагаю вносить свои идеи, фенечки и тонкости, какими пользуетесь при написании проги на ИАРе.

И первый вопрос: - я организовал массив в СИ, с начальным адресом 0х100 и длиной 256 - чар : "__no_init unsigned char MyBuffer [256]@0x100;" - идея сделать кольцевой буффер, для простой работой с указателями (простой инкремент младшего байта указателя), с ним я работаю как в СИ, так и в ассемблере. ?? - как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом?
*


При чем здесь IAR? В С для создания динамического кольцевого буфера используется связка maloc-free. В С++ вообще для создания массивов рекомендуется использовать STL
vet
Цитата(LeoLabs @ May 18 2005, 09:09)
как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом?
*

По идее - так:
Код
 (*(char*)&ptr)++;

или организовать union:
Код
union {
 char low;
 char* value;
} ptr;
...
ptr.low++; //инкремент
...
ch = *ptr.value; //использование указателя
LeoLabs
[/quote]

При чем здесь IAR? В С для создания динамического кольцевого буфера используется связка maloc-free. В С++ вообще для создания массивов рекомендуется использовать STL
*

[/quote]
Что ж не в бровь, а в глаз. Владею СИ я тоже посредственно. Спасибо
vet
Цитата(standpoint @ May 18 2005, 09:16)
При чем здесь IAR? В С для создания динамического кольцевого буфера используется связка maloc-free.
*

Кольцевые буферы в программе обычно интенсивно используются, в т.ч. из прерываний, не зря в DSP они реализуются аппаратно. Использование malloc-free даёт проигрыш по быстродействию и, следовательно, отнимает процессорное время у других задач, не говоря уже о накладных расходах на управление динамической памятью, которые можно позволить себе не на каждом проекте для м/к.
LeoLabs
Standpoint, а вы на чем программируете? не ПиСи ли? а то как-то ответ не "железячника". smile.gif
dxp
Цитата(LeoLabs @ May 18 2005, 11:09)
И первый вопрос: - я организовал массив в СИ, с начальным адресом 0х100 и длиной 256 - чар : "__no_init unsigned char MyBuffer [256]@0x100;" - идея сделать кольцевой буффер, для простой работой с указателями (простой инкремент младшего байта указателя), с ним я работаю как в СИ, так и в ассемблере. ?? - как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом?
*


IAR бывает для очень разных платформ. И тонкие отличия на уровне расширений там разные. Например, в варианте для AVR есть волшебное слово __flash, которого нет в варианте, например, для MSP430, т.к. последний является фон Нейманом, у него стандартное слово const рулит.

Если Вам надо работать только с объектами в младших 8 адресах, то для этого у IAR'а есть специальное волшебное слово __tiny. Т.е. если объявить объект с таким словом, то и размещаться он будет в сегменте TINY_X (X - в зависимости от того, имеет ли объект инициализатор). И указатель для работы с такими объектами тоже надо объявлять соответствующий. И он будет сразу 8-битным, т.е. никакого старшего байта там нет. Например:

Код
   __tiny bool flag;
   ...
   __tiny bool *pFlag = &flag;
   ...
   if(...) *pFlag = true;


Вся арифметика адресов тут 8-битная. За привильность синтаксиса не ручаюсь, давно уже этим не баловался. А проверять лень. smile.gif
freux
Чтобы просто сделать инкремент младшего байта, придется принять ограничение на возможный размер буфера, а именно, - размер может быть, например, 8,16,32,64,128 или 256. И вот почему:

#define BUFFER_SIZE 128 // 0x80
#define BUFFER_MASK (BUFFER_SIZE - 1) // 0x7F
если эту маску накладывать на постоянно увеличивающийся индекс, то мы не выйдем за границы массива

unsigned char Buffer[BUFFER_SIZE];
Превоначально BufferHead, BufferTail указывают на начало массива:
BufferHead = 0;
BufferTail =0;
Затем, данными заполняют буфер, изменяя, например BufferHead.
Читаем буфер, перемещая BufferTail, пока не упрется в BufferHead:

unsigned char tmptail;
unsigned char accum;
if ( BufferHead != BufferTail )
{
/* calculate buffer index */
tmptail = ( BufferTail+ 1 ) & BUFFER_MASK;
BufferTail= tmptail; /* store new index */
accum = Buffer[tmptail];
// дальше используем accum, как надо
}

Инкремент индекса буфера можно написать короче, контролируя при этом сгенеренный код. Вышеприведенный оставил для наглядности
standpoint
Цитата(LeoLabs @ May 18 2005, 09:24)
Standpoint, а вы на чем программируете? не ПиСи ли? а то как-то ответ не "железячника". smile.gif
*

Сорри,
я имел ввиду динамический буфер, а не статический. (Т.е. у которого размер меняется в зависимости от количества поступивших данных/обработанных данных.) Естественно, под каждый элемент буфера выделять память глупо даже для PC, и я этого не предлагал.

Для статического кольцевого буфера существует два пути:
1) косвенная адресация - требует четыре указателя pHead, pTail, сBuf[0] и сBuf[BUFSZ-1], последние два, если buf-глобальный, генерятся в памяти программ.
void Init(){
pHead = pTail = cBuf;
}
void Push(char val){
if(pTail == pHead)
return false;

*pHead = val;

if( pHead == &сBuf[BUFSZ-1])
pHead = cBuf;
else
pHead++;

return true;
}
bool Pop(char val){
if(pTail == pHead)
return false;

char val = *pTail;

if( pTail == &сBuf[BUFSZ-1])
pTail = cBuf;
else
pTail++;

return true;
}

2) индексная: два индекса в памяти данных + константа в памяти программ + указатель на буфер сгенерированный линкером в памяти программ
void Init(){
ixHead = ixTail = 0;
}
bool Push(char val){
if(ixTail == ixHead)
return false;

cBuf[ixHead] = val;

if( ixHead == (BUFSZ-1))
ixHead = 0;
else
ixHead++;

return true;
}
bool Pop(char* val){
if(ixTail == ixHead)
return false;

*val = cBuf[ixTail];

if( ixTail == (BUFSZ-1))
ixTail = 0;
else
ixTail++;

return true;
}

Конструкция
if( ix == (BUFSZ-1))
ix = 0;
else
ix++;
обычно меняется на
ix %= BUFSZ;
Но для IAR - не советуюsmile.gif)

Конкретная реализация выбирается исходя из параметров буфера.

Возможны опечатки и неточности, но смысл в целом таков. Типы указателей я не приводил, для боевого кода советую привести, как это сделал vet, вдруг потом на ARM свою программу будете переносить. Кстати union, предложенный vet в таком виде не переносим, поскольку бывают как big-, так и -little endian uC, а указатели в общем случае не 16-разрядные.

Может выделять память динамически и не совсем целесообразно, просто экономить ресурсы бывает иногда важнее - должна быть золотая середина вот и все. Например, такой вопрос: как встраиваемая система будет обрабатывать ошибку в функции Pop()???

Ко всему, не я же при решении задачи пришел к тому выводу, что мне совершенно необходим буфер размера 0x100 по адресу 0x100, и задачу необходимо решать именно на AVR,- так что в этом смысле я, возможно, и не "железячник":)))) А может быть просто не стоит забивать гвозди микроскопом?wink.gif
-Tумблер-
Цитата(LeoLabs @ May 18 2005, 08:09)
И первый вопрос: - я организовал массив в СИ, с начальным адресом 0х100 и длиной 256 - чар : "__no_init unsigned char MyBuffer [256]@0x100;"

- как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом?


Для работы с таким массивом не выгодно работать с указателем.
(это самый "удобный" массив)
Выгоднее работать с индексом массива - и это как раз байт.

Например:

char wr_pointer=0, rd_pointer=0;

MyBuffer [wr_pointer++] =new_data;// добавление байта с замыканием буфера

или
read_data =MyBuffer[rd_pointer++];// чтение байта с замыканием буфера
smile.gif
vet
Давно не даёт покоя вопрос: реально ли заставить IAR понимать конструкции такого вида:
Код
 printf_P("Hello world\r\n");

Очень уж неудобно под любой ввод-вывод объявлять переменную во FLASH, только чтобы передать её аргументом.
размещение строк в статической памяти не предлагать smile.gif
Andrew_Q
Цитата(vet @ May 27 2005, 13:27)
Давно не даёт покоя вопрос: реально ли заставить IAR понимать конструкции такого вида:
Код
 printf_P("Hello world\r\n");

Очень уж неудобно под любой ввод-ввод объявлять переменную во FLASH, только чтобы передать её аргументом.
размещение строк в статической памяти не предлагать smile.gif
*

Все просто : Project->Options->ICCAVR->Extra Options ставим галку и добавляем в окно магические слова --string_literals_in_flash
IgorKossak
Цитата(LeoLabs @ May 18 2005, 08:09)
...
И первый вопрос: - я организовал массив в СИ, с начальным адресом 0х100 и длиной 256 - чар : "__no_init unsigned char MyBuffer [256]@0x100;" - идея сделать кольцевой буффер, для простой работой с указателями (простой инкремент младшего байта указателя), с ним я работаю как в СИ, так и в ассемблере. ?? - как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом?
*

Сразу несколько неверных, на мой взгляд, подходов (очевидно, перенятых из техники программирования на низкои уровне, но даже там это плохо):
1 - указывать вручную размещение - плохо (непереносимо, гнездилище багов, ограничение возможностей оптимизации, ...);
2 - работать с частью указателя (как и любого другого целостного объекта) - плохо по тем же причинам.
Естественно, если этих трюков не делать - возникает оверхед. При этом надо взвесить, стОит ли такой геморрой свеч ради экономии 5% времени и объёма кода. Ведь если сильно поджимает, а это бывает КРАЙНЕ редко, то можно и кварц побыстрее поставить и МК помощнее взять.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.