Перейти к содержанию
    

Виртуозное владение IARом

Предлагаю открыть новую тему, помогающую овладеть всеми хитростями IARa всем начинающим. Также предлагаю вносить свои идеи, фенечки и тонкости, какими пользуетесь при написании проги на ИАРе.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Предлагаю открыть новую тему, помогающую овладеть всеми хитростями IARa всем начинающим. Также предлагаю вносить свои идеи, фенечки и тонкости, какими пользуетесь при написании проги на ИАРе.

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

По идее - так:

  (*(char*)&ptr)++;

или организовать union:

union {
 char low;
 char* value;
} ptr;
...
ptr.low++; //инкремент
...
ch = *ptr.value; //использование указателя

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

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

Что ж не в бровь, а в глаз. Владею СИ я тоже посредственно. Спасибо

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Кольцевые буферы в программе обычно интенсивно используются, в т.ч. из прерываний, не зря в DSP они реализуются аппаратно. Использование malloc-free даёт проигрыш по быстродействию и, следовательно, отнимает процессорное время у других задач, не говоря уже о накладных расходах на управление динамической памятью, которые можно позволить себе не на каждом проекте для м/к.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И первый вопрос: - я организовал массив в СИ, с начальным адресом 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-битная. За привильность синтаксиса не ручаюсь, давно уже этим не баловался. А проверять лень. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чтобы просто сделать инкремент младшего байта, придется принять ограничение на возможный размер буфера, а именно, - размер может быть, например, 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, а вы на чем программируете? не ПиСи ли? а то как-то ответ не "железячника". :)

Сорри,

я имел ввиду динамический буфер, а не статический. (Т.е. у которого размер меняется в зависимости от количества поступивших данных/обработанных данных.) Естественно, под каждый элемент буфера выделять память глупо даже для 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 - не советую:))

 

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

 

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

 

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

 

Ко всему, не я же при решении задачи пришел к тому выводу, что мне совершенно необходим буфер размера 0x100 по адресу 0x100, и задачу необходимо решать именно на AVR,- так что в этом смысле я, возможно, и не "железячник":)))) А может быть просто не стоит забивать гвозди микроскопом?;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И первый вопрос: - я организовал массив в СИ, с начальным адресом 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++];// чтение байта с замыканием буфера

:)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Давно не даёт покоя вопрос: реально ли заставить IAR понимать конструкции такого вида:

  printf_P("Hello world\r\n");

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

размещение строк в статической памяти не предлагать :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Давно не даёт покоя вопрос: реально ли заставить IAR понимать конструкции такого вида:

  printf_P("Hello world\r\n");

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

размещение строк в статической памяти не предлагать :)

Все просто : Project->Options->ICCAVR->Extra Options ставим галку и добавляем в окно магические слова --string_literals_in_flash

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

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

Сразу несколько неверных, на мой взгляд, подходов (очевидно, перенятых из техники программирования на низкои уровне, но даже там это плохо):

1 - указывать вручную размещение - плохо (непереносимо, гнездилище багов, ограничение возможностей оптимизации, ...);

2 - работать с частью указателя (как и любого другого целостного объекта) - плохо по тем же причинам.

Естественно, если этих трюков не делать - возникает оверхед. При этом надо взвесить, стОит ли такой геморрой свеч ради экономии 5% времени и объёма кода. Ведь если сильно поджимает, а это бывает КРАЙНЕ редко, то можно и кварц побыстрее поставить и МК помощнее взять.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...