|
Виж темите без отговор | Виж активните теми
Дата и час: Пон Юли 27, 2026 4:05 pm
| Автор |
Съобщение |
|
Nikola Kirov
Ранг: Форумен бог
Регистриран на: Нед Окт 31, 2004 9:19 pm Мнения: 4464 Местоположение: Stara Zagora
|
 FIFO буфер за команди
Значи първо да опиша какво искам да направя.
Искам да организирам FIFO буфер в които да имам указатели към функции и съответните им входни аргументи.
Целта на занятието е някои процедури на прекъсвания да записват указател към функция и входни аргументи в опашката на буфера. A в main() да имам цикъл които последователно да вади указателите от буфера и да извиква функциите като им дава съответните аргументи.
Ако се работи само с функции без входни аргументи ми е ясно.
Ако се работи само с функции с един тип аргументи с малко експерименти ще го наглася някак. Но как стои въпроса ако искам този буфер да поддържа и функции с различен тип входни аргументи и каква е стандартната реализация в C?
|
| Сря Юни 08, 2005 9:56 pm |
|
 |
|
danov
Ранг: Минаващ
Регистриран на: Вто Ное 16, 2004 4:43 pm Мнения: 85 Местоположение: София
|
 Re: FIFO буфер за команди
Чак стандартна реализация - не знам да има. Но може да направиш всички функции да имат един аргумент - указател към структура, която съдържа параметрите. По този начин ще е лесно да си направиш FIFO-то.
|
| Сря Юни 08, 2005 10:20 pm |
|
 |
|
Nikola Kirov
Ранг: Форумен бог
Регистриран на: Нед Окт 31, 2004 9:19 pm Мнения: 4464 Местоположение: Stara Zagora
|
Трябва ми по универсално решение. Да мога да работя с до 2 аргумента и без аргумент. Ако ги направя всички функции да си вадят сами параметрите от структура това ще ми усложни живота с поставянето на параметрите в тая структура при задаването на параметрите на функцията.
Това ли ми е единственото решение?
|
| Сря Юни 08, 2005 10:30 pm |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
Syntax
#include <stdarg.h>
void va_start(va_list ap, lastfix);
type va_arg(va_list ap, type);
void va_end(va_list ap);
Description
Implement a variable argument list.
Some C functions, such as vfprintf and vprintf, take variable argument lists in addition to taking a number of fixed (known) parameters. The va_arg, va_end, and va_start macros provide a portable way to access these argument lists. They are used for stepping through a list of arguments when the called function does not know the number and types of the arguments being passed.
The header file stdarg.h declares one type (va_list) and three macros (va_start, va_arg, and va_end).
va_list: This array holds information needed by va_arg and va_end. When a called function takes a variable argument list, it declares a variable ap of type va_list.
va_start: This routine (implemented as a macro) sets ap to point to the first of the variable arguments being passed to the function. va_start must be used before the first call to va_arg or va_end.
va_start takes two parameters: ap and lastfix. (ap is explained under va_list in the preceding paragraph; lastfix is the name of the last fixed parameter being passed to the called function.)
va_arg: This routine (also implemented as a macro) expands to an expression that has the same type and value as the next argument being passed (one of the variable arguments). The variable ap to va_arg should be the same ap that va_start initialized.
Note: Because of default promotions, you cannot use char, unsigned char, or float types with va_arg.
The first time va_arg is used, it returns the first argument in the list. Each successive time va_arg is used, it returns the next argument in the list. It does this by first dereferencing ap, and then incrementing ap to point to the following item. va_arg uses the type to both perform the dereference and to locate the following item. Each successive time va_arg is invoked, it modifies ap to point to the next argument in the list.
va_end: This macro helps the called function perform a normal return. va_end might modify ap in such a way that it cannot be used unless va_start is recalled. va_end should be called after va_arg has read all the arguments; failure to do so might cause strange, undefined behavior in your program.
Return Value
va_start and va_end return no values; va_arg returns the current argument in the list (the one that ap is pointing to).
#include <stdio.h>
#include <stdarg.h>
/* calculate sum of a 0 terminated list */
void sum(char *msg, ...)
{
int total = 0;
va_list ap;
int arg;
va_start(ap, msg);
while ((arg = va_arg(ap,int)) != 0) {
total += arg;
}
printf(msg, total);
va_end(ap);
}
int main(void) {
sum("The total of 1+2+3+4 is %d\n", 1,2,3,4,0);
return 0;
}
Доколкото разбирам обаче ти трябва реализация на горните макроси за микроконтролери, а не си спомням да съм срещал в който и да Ц компилатор такава реализация за микроконтролери.
|
| Чет Юни 09, 2005 12:11 am |
|
 |
|
Nikola Kirov
Ранг: Форумен бог
Регистриран на: Нед Окт 31, 2004 9:19 pm Мнения: 4464 Местоположение: Stara Zagora
|
Въртеше ми се в главата че съм виждал нещо такова. И затова повдигнах въпроса. Само дето не се поддържа от IAR.  А и като се замисля за реализацията наистина едва ли има някой компилатор за микроконтролери дето да го поддържа.
Явно ще се гърча да го измислям някак си.Малко неприятна задача за новобранец в програмирането,но така се учел човек.
|
| Чет Юни 09, 2005 12:39 am |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
Това, което ти предлага колегата Danov, е удачно решение, само че при различни по тип аргументи трябва полетата в структурата да са union. Ако нямаш параметър, указателя към структурата ти е NULL, ако е 1 параметър, указателя е различен от NULL и първото поле -union в структурата ти е валидно, при 2 второто и т.н. Това че ще попълваш тези параметри преди извикването на дадена функци не е чак толкова голям проблем. Например CCS C компилатора за ПИК, дори и един параметър от тип int8 да има дадена функция, ще го предаде през регистър, а не през акумулатора, както бих го направил на асемблер. Ако извикаш една функция 100 пъти, ти изразходва 100 байта повече памет, затова се принуждавам за често извикваните функции да си правя макроси, с които да предавам променливата през акумулатора.
|
| Чет Юни 09, 2005 12:52 am |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
Пирев, що да изразходва памет. Набеди ги да са Ауто - те в стека. Е ако не барзаш и програмната памет не ти е кът. Иначе - глобални. Абе то при микроконтролерите от тоя калибър (8 бита, до 16К флаш, до 3К рам) то човек рядко си позволява да прави такива еквилибристики като указатели към функции и пр. Там С- то си е просто по прегледен асемблер.
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Чет Юни 09, 2005 9:12 am |
|
 |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
До колко тоя CSS е ANSI-съвместим? Поддържа ли malloc & free?
|
| Чет Юни 09, 2005 9:52 am |
|
 |
|
Nikola Kirov
Ранг: Форумен бог
Регистриран на: Нед Окт 31, 2004 9:19 pm Мнения: 4464 Местоположение: Stara Zagora
|
Поддържа malloc & free.
А като ви се налага да правите опашка от задачи как го правите. На мен ми доиде само този метод на ум но това не означава че няма друг по добър.
Подобна опашка от задачи ми се вижда много добра алтернатива на RTOS за контролерите. Нещата които трябва да се изпълняват веднага се правят направо в функциите на прекъсванията а всичко останало,особенно по бавни задачи като писане по дисплея,запис в някакво устроиство с последователен интерфеис или нещо подобно отива на опашката с задачи. Така се решава и проблема когато 2 задачи ползват едни и същи I/O ресурси,те просто се изпълняват последователно. Това разбира се когато има достатъчно памет.
|
| Чет Юни 09, 2005 12:17 pm |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
Ами то твойто си е много близко до cooperative RTOS, да не казвам че е същото. Много задачи които се изпълняват самосточтелно и сами определят кога да приключат.
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Чет Юни 09, 2005 1:46 pm |
|
 |
|
danov
Ранг: Минаващ
Регистриран на: Вто Ное 16, 2004 4:43 pm Мнения: 85 Местоположение: София
|
 stdarg
gcc поддържа stdarg - поне за avr и msp430.
|
| Чет Юни 09, 2005 2:23 pm |
|
 |
|
Nikola Kirov
Ранг: Форумен бог
Регистриран на: Нед Окт 31, 2004 9:19 pm Мнения: 4464 Местоположение: Stara Zagora
|
Че RTOS не поддържа ли различни нишки като превключва между тях и разпределя ресурсите на процесора между тях. Идеята тук е да имаме само една нишка която да е опашка от команди.
|
| Чет Юни 09, 2005 2:56 pm |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
Имах предвид следното:
CCS компилатора прави следното: вътре SomeFunc изглежда така: Докато, пишейки на асемблер, правя следното: , при което SomeFunc изглежда така:
Друг C компилатор за PIC-ове, този на Knudsen ( CC5X ) такова извикване го прави винаги през акумулатора. Наскоро се ядосвах на това викане на подпрограми на CCS, защото една стара програма на асемблер, трябваше да я преработя на C, за да мога по-лесно да добавям нови неща, едвам успях да я събера в PIC16F872, разликата м/у асемблер и CCS C се оказа около 350 байта в полза на асемблера.
|
| Чет Юни 09, 2005 3:03 pm |
|
 |
|
0x00
Ранг: Минаващ
Регистриран на: Пет Мар 18, 2005 4:14 pm Мнения: 67 Местоположение: Русе.BG/Oldenburg.DE
|
Не съм много advanced в програмирането за MCUs, но:
@Nikola Kirov: Защо до ти се усложнява живота при решението с указателите към структурата? Дефинирай си извикваща ф-я int callPop(int a, int b) и си работи с нея. Самата ф-я може да записва параметрите на предварително определен адрес (например глобални temp1 и temp2), след това вика ф-ята от опашката. Всяка ф-я от списъка я дефинираш като int foo(void), а в самите ф-ии:
retrieveParams може да ги декларираш като макрос, за да избегнеш overhead-a от извикване но ф-я (прехвърлянето на параметри, etc). Мисля това решение е добър компромис м/у бързодействие и леснота (има ли такава дума?  ) на използване.
И без това, в другия случай ще трябва да typecast-ваш pointer-а към всяка отделна ф-я.
П.С Всъщност този компилатор подържа ли naked ф-ии?
|
| Чет Юни 09, 2005 4:24 pm |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
Пирев, така е защото използваш статични променливи. Всеки С компилатор поддържа статични и динамични промнливи. Вторите се блъскат в стека, и се унищожават извън функцията. Разбира се динамични могат да са само локални променливи, които нямат значение от вън на функцията.
Са друг е въпроса на CCS как му е сетнато по дефаулт, сигурно е на статични, щото 16ката няма много ресурси за стек. И затова по презумпция маа в регистрите за всяка променлива - локална или глобална.
Моя компилатор има и тип overlay, това са статични променливи които ползват общ регистър, е не едновремнно.
Но това май няма отношение по темата.
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Чет Юни 09, 2005 7:02 pm |
|
|
Кой е на линия |
Потребители разглеждащи този форум: 0 регистрирани и 9 госта |
|
Вие не можете да пускате нови теми Вие не можете да отговаряте на теми Вие не можете да променяте собственото си мнение Вие не можете да изтривате собствените си мнения Вие не можете да прикачвате файл
|
|