| Микроконтролери и електроника http://mcu-bg.com/mcu_site/ |
|
| Един CALL до много функции... http://mcu-bg.com/mcu_site/viewtopic.php?f=3&t=11913 |
Страница 1 от 3 |
| Автор: | Vesko [ Нед Ное 17, 2013 6:01 pm ] |
| Заглавие: | Един CALL до много функции... |
Май заглавието не се получи В линкер скрипт файла: __init_proc = .; KEEP (*(.INIT_PROC)) LONG (0) Дефинирам си функция, която си извиква в опреленмомент на инициализациа на системата: #define __INIT_PROC(x) void x (void); \ void * x##_p __attribute__ ((section(".INIT_PROC"))) = & x; \ void x (void) и го ползвам: __INIT_PROC(modelename) { } Някъде при инициализация: extern uint32_t __init_proc; static void _ExecuteProc(uint32_t *fp) { while(*fp) { ((void (*)(void))(*fp))(); fp ++; } } _ExecuteProc(&__init_proc); Механизма си работи много добре. Но, винаги имаедно но. Като искам да добавя нов тип/клас такав броадкаст трябва да променям линкер файла. Дали има по-прост начин да реализирам този механизъм? Или просто да мога да дописвам линкер скрипта през прагма директиви на С компилатора? |
|
| Автор: | miro_atc [ Нед Ное 17, 2013 8:16 pm ] |
| Заглавие: | Re: Един CALL до много функции... |
Vesko, не ме вкарвай в грях да тръгна точно на теб да обяснявам как работи компилатора Доколкото разбирам проблемът ти е как да изградиш една статична структура от различни сорс файлове, т.е. единици. Принципно няма стандартно решение, само вариантът със секциите, но ти си го знаеш... Другият вариант са динамични структури. Може чисто Ц, може и Ц++. Правиш си едно класче за списък/масив и едно за калбак, правиш ги статични и в конструктурите си правиш регистрациите. Ако отидеш малко по-далеч в Ц++ може да ползваш шаблони, примерно array и с push_back() регистрираш. Предимството е, че ако е възможно регистрациите и някои операции ще ги направи compile time. |
|
| Автор: | michev [ Нед Ное 17, 2013 8:16 pm ] |
| Заглавие: | Re: Един CALL до много функции... |
А защо просто не си направиш един елементарен стек, в който да набуташ всички указатели към функции които искаш да се извикат в даден момент, и като настъпи въпросния момент - да ги извикаш една по една? |
|
| Автор: | Vesko [ Нед Ное 17, 2013 9:13 pm ] |
| Заглавие: | Re: Един CALL до много функции... |
Варианта със секциите работи, ама си е много хамалогия за всеки един списък да преправям скрипт файла. Чудя се как да взема началото и края на дадена секция от С кода, без да ползвам PROVIDE в скрипта.... Но май не откривам за сега начин. Вариантите да си изграждам опашки или статични масиви с функции, който трябва да викам не ми харесва. Тогава като даден файл го махна от компилацията, някой трябва да се погрижи да го махне от статичният списък... |
|
| Автор: | palavrov [ Нед Ное 17, 2013 10:59 pm ] |
| Заглавие: | Re: Един CALL до много функции... |
Тъпанарско решение, ама сигурно ще ти свърши работа - лека модификация на твоя код: __init_struct = .; KEEP (*(.INIT_PROC)) LONG (0) LONG (0) enum init_proc_class { CLASS_1, CLASS_2, ...}; struct init_struct { enum init_proc_class class, void (*handler)(void); } #define __INIT_PROC(c, p) void p (void); \ struct init_struct __init_struct_##c##_##p##__ __attribute__((section(".INIT_PROC))) = { .class = class, handler = &p }; \ void p (void) extern struct init_struct __init_struct[]; static void _ExecuteProc(enum init_class class) { for(struct *init_struct = __init_struct; init_struct->handler!=NULL; init_struct++) if(init_struct->class == class) init_struct->handler(); } |
|
| Автор: | Vesko [ Пон Ное 18, 2013 12:01 am ] |
| Заглавие: | Re: Един CALL до много функции... |
Всашност в монета работи точно така. Ама предпочитам предишният метод. Исновната причина да търся друг подход е следната. Цялата ми концепция е на 1мС да ми се изпълняват определени функции. С цел по-ниска консумация си свалям клока. Обаче се оказва, че да сканирам структурата за определено ИД е по-бавно от 1мС..... |
|
| Автор: | miro_atc [ Пон Ное 18, 2013 12:11 am ] | |||||||||
| Заглавие: | Re: Един CALL до много функции... | |||||||||
Ма кой ти каза да правиш статични... аз предложих динамичен масив/списък. Който иска да получава нотификации си се регистрира сам. Като му махнеш сорса няма кой да го вкара в списъка. |
||||||||||
| Автор: | palavrov [ Пон Ное 18, 2013 12:23 am ] | ||||||||||||||||||
| Заглавие: | Re: Един CALL до много функции... | ||||||||||||||||||
За да се регистрира сам пак трябва някой да го извика ... т.е. стигаш до същия проблем. Веско, ако паметта не е проблем за да ускориш изпълнението може да си направиш някакъв кеш. Но при всички случаи си е простотия - нещо може ли да се свърши компиле тайм не трябва да се прави рън тайм. По скоро виж за някакъв твой си препроцесор който да анализира сорсовете и да подготвя линкерския скрипт - едно допълнително изискване в мейкфайла и всичко ще работи автоматично. |
|||||||||||||||||||
| Автор: | palavrov [ Пон Ное 18, 2013 12:34 am ] | |||||||||
| Заглавие: | Re: Един CALL до много функции... | |||||||||
Предполагам си се сетил и сам, ама все пак да обърна внимание. Не знам колко е намаления клок, нито броя на фунцкиите за този броадкаст, но 1мс си е доста време - дали не се бавиш прекалено много в някоя от функциите? Тогава каквито и хватки да правиш няма да паднеш под 1мс. Вземи му пусни някакъв профайлър да видиш къде колко се баву. Така като те слушам правиш нещо с микроконтролер - за да не си разбутваш кода с външен профайлър, клати един пин във всяка итерация на този цикъл, запиши го с един логически анализатор и виж после има ли нещо съмнително. Клатенето на пина трябва да е 1-2 инструкции, така че няма съществено да изкриви времената. |
||||||||||
| Автор: | miro_atc [ Пон Ное 18, 2013 12:35 am ] | |||||||||
| Заглавие: | Re: Един CALL до много функции... | |||||||||
При Ц++ се викат конструкторите на всички статични (разбирай глобални) обекти верно пак по същия начин чрез секции, но поне е стандартно и се предполага че *вече* е направено за всяка Ц++ система. |
||||||||||
| Автор: | palavrov [ Пон Ное 18, 2013 12:44 am ] | |||||||||
| Заглавие: | Re: Един CALL до много функции... | |||||||||
Ц++ не е хубаво решение точно за такива проблеми, верно че конструкторите на статичните обекти се викат автоматично и само толкова. В момента в който ти потрябва нещо по засукано и си дотам - например не може да контролираш реда в който ще се извикат а това не е без значение - концептуално не е измислено, решението е пак със специфични хватки. Не се заяждам - просто според мен ако проблема може да се реши на чисто Ц няма смисъл да се ползва Ц++ - само се утежнява кода. |
||||||||||
| Автор: | miro_atc [ Пон Ное 18, 2013 12:56 am ] |
| Заглавие: | Re: Един CALL до много функции... |
Ми аз вече казах, че на чисто Ц няма чисто решение Ц++ има всички възможности на Ц плюс още, включително ако щеш и за реда на инициализациите има. А това че утежнявал кода са пълни глупости, напротив точно обратното е, особено ако ползваш шаблони и ги ползваш разумно. |
|
| Автор: | Vesko [ Пон Ное 18, 2013 7:38 am ] |
| Заглавие: | Re: Един CALL до много функции... |
На чисто Ц има __attribute__((constructor)) и се извикват преди мейна. Ако разширението на GCC може да се приеме за чисто Ц. Така че вариянта с регистрацията си остава, но заема РАМ. А клока, като го сваля под 2МХц не успявам да си завътя цикъла да викам един броадкаст през таблица (която сканирам линейноза определено ИД) и на влизам през 1милисек в прекъсване (и на всяко прекъсване се викат неизвесно колко функции). Може би заради оследното ми е проблема, те всъщност не съм сигурен, че ми трябват точно в този момент.... |
|
| Автор: | palavrov [ Пон Ное 18, 2013 10:26 am ] | |||||||||
| Заглавие: | Re: Един CALL до много функции... | |||||||||
Я дай пример как се променя реда на инициализация? Аз не знам за такъв и ми е любопитно С Ц++ не се занимавам доста време и съм спрял да следя какви новости има по него. За утежняването - утежняване е когато за да се свърши дадена работа трябва да се изпише повече сорс или да се изпълни повече код. Решението на Веско е в 15-на реда - виж колко ще излезе на Ц++ |
||||||||||
| Автор: | gicho [ Пон Ное 18, 2013 10:29 am ] |
| Заглавие: | Re: Един CALL до много функции... |
Защо не помислиш от друга гледна точка - да ускориш викането. Имам предвид че това търсене на ИД в таблица е бабешки метод, организирай си (някакво подобие на) лист и си ги викай. Предполагам че ускоряването на търсенето примерно 10 пъти ще ти реши проблема директно. Ако искаш някаква гъвкавост можеш да го направиш и на pre-build стъпка, нещо като код генератор. Слагаш в публичния хедър на разните компоненти един define/macro с типа на event-а и посветената функция за извикване (callback-а). После обиколи си хедърите/сорсовете и извади тия декларация, генерирай сорса който да ти ги вика и си готов. Цялата тая работа трябва да се свърши от скрипт някакъв, разбира се. Генерално проблемът ти не ми е много чист- добавяйки код (модул, компонент) в някакъв проект иска да го "интегрираш". Такова интегриране реално се описва с таблицата кои функции на кое събитие да се викат. Най-малкото трябва да създадеш инстанция от тоя код (конструктора). Като се съгласиш че това е необходимо, ще видиш че има много начини да направиш "интеграцията" тръгвайки от там. Визирам инстанцията на компонента при създаването си извършва регистрация за дадени събития, които я вълнуват (publish-subscribe). Ако искаш да е само build time, имплементацията ти на publish-subscribe почва да работи със статична таблица. Тая таблица обикновено е масив или списък от списъци. Как да вкараш описанието на новия ти модул в тази таблица? Или ръчно (ти го описваш някъде), или със скрипт който търси нещо специфично. Или задавайки конструктор в c++. И друго нещо базово - постановката с "нисък клок" и "polling на 1мс" обикновено е много далеко от power-efficient код. Едит: те колегите пуснали повечето от нещата вече. Като бележка през линкера няма да можеш да направиш функциите inline. Което е възможно ако го направиш с код генератор. |
|
| Страница 1 от 3 | Часовете са според зоната UTC + 2 часа [ DST ] |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|