LeoLabs 0 18 мая, 2005 Опубликовано 18 мая, 2005 · Жалоба Предлагаю открыть новую тему, помогающую овладеть всеми хитростями IARa всем начинающим. Также предлагаю вносить свои идеи, фенечки и тонкости, какими пользуетесь при написании проги на ИАРе. И первый вопрос: - я организовал массив в СИ, с начальным адресом 0х100 и длиной 256 - чар : "__no_init unsigned char MyBuffer [256]@0x100;" - идея сделать кольцевой буффер, для простой работой с указателями (простой инкремент младшего байта указателя), с ним я работаю как в СИ, так и в ассемблере. ?? - как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
standpoint 0 18 мая, 2005 Опубликовано 18 мая, 2005 · Жалоба Предлагаю открыть новую тему, помогающую овладеть всеми хитростями IARa всем начинающим. Также предлагаю вносить свои идеи, фенечки и тонкости, какими пользуетесь при написании проги на ИАРе. И первый вопрос: - я организовал массив в СИ, с начальным адресом 0х100 и длиной 256 - чар : "__no_init unsigned char MyBuffer [256]@0x100;" - идея сделать кольцевой буффер, для простой работой с указателями (простой инкремент младшего байта указателя), с ним я работаю как в СИ, так и в ассемблере. ?? - как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом? <{POST_SNAPBACK}> При чем здесь IAR? В С для создания динамического кольцевого буфера используется связка maloc-free. В С++ вообще для создания массивов рекомендуется использовать STL Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 18 мая, 2005 Опубликовано 18 мая, 2005 · Жалоба как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом? <{POST_SNAPBACK}> По идее - так: (*(char*)&ptr)++; или организовать union: union { char low; char* value; } ptr; ... ptr.low++; //инкремент ... ch = *ptr.value; //использование указателя Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LeoLabs 0 18 мая, 2005 Опубликовано 18 мая, 2005 · Жалоба При чем здесь IAR? В С для создания динамического кольцевого буфера используется связка maloc-free. В С++ вообще для создания массивов рекомендуется использовать STL <{POST_SNAPBACK}> Что ж не в бровь, а в глаз. Владею СИ я тоже посредственно. Спасибо Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 18 мая, 2005 Опубликовано 18 мая, 2005 · Жалоба При чем здесь IAR? В С для создания динамического кольцевого буфера используется связка maloc-free. <{POST_SNAPBACK}> Кольцевые буферы в программе обычно интенсивно используются, в т.ч. из прерываний, не зря в DSP они реализуются аппаратно. Использование malloc-free даёт проигрыш по быстродействию и, следовательно, отнимает процессорное время у других задач, не говоря уже о накладных расходах на управление динамической памятью, которые можно позволить себе не на каждом проекте для м/к. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LeoLabs 0 18 мая, 2005 Опубликовано 18 мая, 2005 · Жалоба Standpoint, а вы на чем программируете? не ПиСи ли? а то как-то ответ не "железячника". :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 18 мая, 2005 Опубликовано 18 мая, 2005 · Жалоба И первый вопрос: - я организовал массив в СИ, с начальным адресом 0х100 и длиной 256 - чар : "__no_init unsigned char MyBuffer [256]@0x100;" - идея сделать кольцевой буффер, для простой работой с указателями (простой инкремент младшего байта указателя), с ним я работаю как в СИ, так и в ассемблере. ?? - как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом? <{POST_SNAPBACK}> IAR бывает для очень разных платформ. И тонкие отличия на уровне расширений там разные. Например, в варианте для AVR есть волшебное слово __flash, которого нет в варианте, например, для MSP430, т.к. последний является фон Нейманом, у него стандартное слово const рулит. Если Вам надо работать только с объектами в младших 8 адресах, то для этого у IAR'а есть специальное волшебное слово __tiny. Т.е. если объявить объект с таким словом, то и размещаться он будет в сегменте TINY_X (X - в зависимости от того, имеет ли объект инициализатор). И указатель для работы с такими объектами тоже надо объявлять соответствующий. И он будет сразу 8-битным, т.е. никакого старшего байта там нет. Например: __tiny bool flag; ... __tiny bool *pFlag = &flag; ... if(...) *pFlag = true; Вся арифметика адресов тут 8-битная. За привильность синтаксиса не ручаюсь, давно уже этим не баловался. А проверять лень. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
freux 0 18 мая, 2005 Опубликовано 18 мая, 2005 · Жалоба Чтобы просто сделать инкремент младшего байта, придется принять ограничение на возможный размер буфера, а именно, - размер может быть, например, 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 0 18 мая, 2005 Опубликовано 18 мая, 2005 · Жалоба Standpoint, а вы на чем программируете? не ПиСи ли? а то как-то ответ не "железячника". :) <{POST_SNAPBACK}> Сорри, я имел ввиду динамический буфер, а не статический. (Т.е. у которого размер меняется в зависимости от количества поступивших данных/обработанных данных.) Естественно, под каждый элемент буфера выделять память глупо даже для 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,- так что в этом смысле я, возможно, и не "железячник":)))) А может быть просто не стоит забивать гвозди микроскопом?;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
-Tумблер- 0 19 мая, 2005 Опубликовано 19 мая, 2005 · Жалоба И первый вопрос: - я организовал массив в СИ, с начальным адресом 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++];// чтение байта с замыканием буфера :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 27 мая, 2005 Опубликовано 27 мая, 2005 · Жалоба Давно не даёт покоя вопрос: реально ли заставить IAR понимать конструкции такого вида: printf_P("Hello world\r\n"); Очень уж неудобно под любой ввод-вывод объявлять переменную во FLASH, только чтобы передать её аргументом. размещение строк в статической памяти не предлагать :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andrew_Q 0 27 мая, 2005 Опубликовано 27 мая, 2005 · Жалоба Давно не даёт покоя вопрос: реально ли заставить IAR понимать конструкции такого вида: printf_P("Hello world\r\n"); Очень уж неудобно под любой ввод-ввод объявлять переменную во FLASH, только чтобы передать её аргументом. размещение строк в статической памяти не предлагать :) <{POST_SNAPBACK}> Все просто : Project->Options->ICCAVR->Extra Options ставим галку и добавляем в окно магические слова --string_literals_in_flash Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 1 июня, 2005 Опубликовано 1 июня, 2005 · Жалоба ... И первый вопрос: - я организовал массив в СИ, с начальным адресом 0х100 и длиной 256 - чар : "__no_init unsigned char MyBuffer [256]@0x100;" - идея сделать кольцевой буффер, для простой работой с указателями (простой инкремент младшего байта указателя), с ним я работаю как в СИ, так и в ассемблере. ?? - как сделать инкремент младшего байта указателя в СИ? и вообще работать только с младшим байтом? <{POST_SNAPBACK}> Сразу несколько неверных, на мой взгляд, подходов (очевидно, перенятых из техники программирования на низкои уровне, но даже там это плохо): 1 - указывать вручную размещение - плохо (непереносимо, гнездилище багов, ограничение возможностей оптимизации, ...); 2 - работать с частью указателя (как и любого другого целостного объекта) - плохо по тем же причинам. Естественно, если этих трюков не делать - возникает оверхед. При этом надо взвесить, стОит ли такой геморрой свеч ради экономии 5% времени и объёма кода. Ведь если сильно поджимает, а это бывает КРАЙНЕ редко, то можно и кварц побыстрее поставить и МК помощнее взять. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться