|
|
  |
Виртуозное владение IARом, предлагаю маленький подфорум |
|
|
|
May 18 2005, 05:16
|
Группа: Новичок
Сообщений: 11
Регистрация: 4-05-05
Пользователь №: 4 743

|
Цитата(LeoLabs @ May 18 2005, 08:09) Предлагаю открыть новую тему, помогающую овладеть всеми хитростями IARa всем начинающим. Также предлагаю вносить свои идеи, фенечки и тонкости, какими пользуетесь при написании проги на ИАРе. И первый вопрос: - я организовал массив в СИ, с начальным адресом 0х100 и длиной 256 - чар : "__no_init unsigned char MyBuffer [256]@0x100;" - идея сделать кольцевой буффер, для простой работой с указателями (простой инкремент младшего байта указателя), с ним я работаю как в СИ, так и в ассемблере. ?? - как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом? При чем здесь IAR? В С для создания динамического кольцевого буфера используется связка maloc-free. В С++ вообще для создания массивов рекомендуется использовать STL
|
|
|
|
|
May 18 2005, 05:26
|
Знающий
   
Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32

|
Цитата(LeoLabs @ May 18 2005, 09:09) как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом? По идее - так: Код (*(char*)&ptr)++; или организовать union: Код union { char low; char* value; } ptr; ... ptr.low++; //инкремент ... ch = *ptr.value; //использование указателя
--------------------
Главная линия этого опуса ясна мне насквозь!
|
|
|
|
|
May 18 2005, 06:07
|

Участник

Группа: Новичок
Сообщений: 47
Регистрация: 5-03-05
Пользователь №: 3 082

|
[/quote] При чем здесь IAR? В С для создания динамического кольцевого буфера используется связка maloc-free. В С++ вообще для создания массивов рекомендуется использовать STL [/quote] Что ж не в бровь, а в глаз. Владею СИ я тоже посредственно. Спасибо
|
|
|
|
|
May 18 2005, 06:20
|
Знающий
   
Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32

|
Цитата(standpoint @ May 18 2005, 09:16) При чем здесь IAR? В С для создания динамического кольцевого буфера используется связка maloc-free. Кольцевые буферы в программе обычно интенсивно используются, в т.ч. из прерываний, не зря в DSP они реализуются аппаратно. Использование malloc-free даёт проигрыш по быстродействию и, следовательно, отнимает процессорное время у других задач, не говоря уже о накладных расходах на управление динамической памятью, которые можно позволить себе не на каждом проекте для м/к.
--------------------
Главная линия этого опуса ясна мне насквозь!
|
|
|
|
|
May 18 2005, 07:02
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(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-битная. За привильность синтаксиса не ручаюсь, давно уже этим не баловался. А проверять лень.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
May 18 2005, 07:10
|
Участник

Группа: Новичок
Сообщений: 41
Регистрация: 7-02-05
Пользователь №: 2 473

|
Чтобы просто сделать инкремент младшего байта, придется принять ограничение на возможный размер буфера, а именно, - размер может быть, например, 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, как надо }
Инкремент индекса буфера можно написать короче, контролируя при этом сгенеренный код. Вышеприведенный оставил для наглядности
|
|
|
|
|
May 18 2005, 18:59
|
Группа: Новичок
Сообщений: 11
Регистрация: 4-05-05
Пользователь №: 4 743

|
Цитата(LeoLabs @ May 18 2005, 09:24) 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,- так что в этом смысле я, возможно, и не "железячник":)))) А может быть просто не стоит забивать гвозди микроскопом?
|
|
|
|
|
May 19 2005, 06:11
|

Частый гость
 
Группа: Свой
Сообщений: 146
Регистрация: 4-11-04
Из: Московская область
Пользователь №: 1 040

|
Цитата(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++];// чтение байта с замыканием буфера
--------------------
- ЗАМЕНЯТЬ ДЕТАЛИ НА ХОДУ ВОСПРЕЩАЕТСЯ !!! -
|
|
|
|
|
May 27 2005, 08:27
|
Знающий
   
Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32

|
Давно не даёт покоя вопрос: реально ли заставить IAR понимать конструкции такого вида: Код printf_P("Hello world\r\n"); Очень уж неудобно под любой ввод-вывод объявлять переменную во FLASH, только чтобы передать её аргументом. размещение строк в статической памяти не предлагать
--------------------
Главная линия этого опуса ясна мне насквозь!
|
|
|
|
|
May 27 2005, 08:52
|
Группа: Участник
Сообщений: 7
Регистрация: 27-05-05
Пользователь №: 5 449

|
Цитата(vet @ May 27 2005, 13:27) Давно не даёт покоя вопрос: реально ли заставить IAR понимать конструкции такого вида: Код printf_P("Hello world\r\n"); Очень уж неудобно под любой ввод-ввод объявлять переменную во FLASH, только чтобы передать её аргументом. размещение строк в статической памяти не предлагать  Все просто : Project->Options->ICCAVR->Extra Options ставим галку и добавляем в окно магические слова --string_literals_in_flash
|
|
|
|
|
Jun 1 2005, 16:00
|

Шаман
     
Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221

|
Цитата(LeoLabs @ May 18 2005, 08:09) ... И первый вопрос: - я организовал массив в СИ, с начальным адресом 0х100 и длиной 256 - чар : "__no_init unsigned char MyBuffer [256]@0x100;" - идея сделать кольцевой буффер, для простой работой с указателями (простой инкремент младшего байта указателя), с ним я работаю как в СИ, так и в ассемблере. ?? - как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом? Сразу несколько неверных, на мой взгляд, подходов (очевидно, перенятых из техники программирования на низкои уровне, но даже там это плохо): 1 - указывать вручную размещение - плохо (непереносимо, гнездилище багов, ограничение возможностей оптимизации, ...); 2 - работать с частью указателя (как и любого другого целостного объекта) - плохо по тем же причинам. Естественно, если этих трюков не делать - возникает оверхед. При этом надо взвесить, стОит ли такой геморрой свеч ради экономии 5% времени и объёма кода. Ведь если сильно поджимает, а это бывает КРАЙНЕ редко, то можно и кварц побыстрее поставить и МК помощнее взять.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|