Отговори на тема  [ 37 мнения ]  Отиди на страница 1, 2, 3  Следваща
Един CALL до много функции... 
Автор Съобщение
Ранг: Популярен
Ранг: Популярен

Регистриран на: Пон Мар 22, 2010 8:52 pm
Мнения: 328
Мнение Един CALL до много функции...
Май заглавието не се получи :) Та накратко трябва ми да пратя нещо като броадкаст до няколко рецепиента. Но предварително не знам колко са. Например като успея да направя ВиФи връзка да информирам системата си, че вече има работещ ВиФи и съответно като отпадне. До сега си правих подобни неща като дефинирам 3 сегмента. Например:

В линкер скрипт файла:
__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);

Механизма си работи много добре. Но, винаги имаедно но. Като искам да добавя нов тип/клас такав броадкаст трябва да променям линкер файла.

Дали има по-прост начин да реализирам този механизъм? Или просто да мога да дописвам линкер скрипта през прагма директиви на С компилатора?


Нед Ное 17, 2013 6:01 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11266
Местоположение: Добрич
Мнение Re: Един CALL до много функции...
Vesko, не ме вкарвай в грях да тръгна точно на теб да обяснявам как работи компилатора ;-)


Доколкото разбирам проблемът ти е как да изградиш една статична структура от различни сорс файлове, т.е. единици. Принципно няма стандартно решение, само вариантът със секциите, но ти си го знаеш...

Другият вариант са динамични структури. Може чисто Ц, може и Ц++. Правиш си едно класче за списък/масив и едно за калбак, правиш ги статични и в конструктурите си правиш регистрациите.

Ако отидеш малко по-далеч в Ц++ може да ползваш шаблони, примерно array и с push_back() регистрираш. Предимството е, че ако е възможно регистрациите и някои операции ще ги направи compile time.


Нед Ное 17, 2013 8:16 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Сря Юли 11, 2007 10:16 am
Мнения: 1730
Мнение Re: Един CALL до много функции...
А защо просто не си направиш един елементарен стек, в който да набуташ всички указатели към функции които искаш да се извикат в даден момент, и като настъпи въпросния момент - да ги извикаш една по една?


Нед Ное 17, 2013 8:16 pm
Профил
Ранг: Популярен
Ранг: Популярен

Регистриран на: Пон Мар 22, 2010 8:52 pm
Мнения: 328
Мнение Re: Един CALL до много функции...
Варианта със секциите работи, ама си е много хамалогия за всеки един списък да преправям скрипт файла. Чудя се как да взема началото и края на дадена секция от С кода, без да ползвам PROVIDE в скрипта.... Но май не откривам за сега начин.

Вариантите да си изграждам опашки или статични масиви с функции, който трябва да викам не ми харесва. Тогава като даден файл го махна от компилацията, някой трябва да се погрижи да го махне от статичният списък...


Нед Ное 17, 2013 9:13 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Окт 11, 2011 11:53 pm
Мнения: 4582
Местоположение: Brussels / Пловдив
Мнение 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();
}

_________________
Мразя да мразя ...


Нед Ное 17, 2013 10:59 pm
Профил
Ранг: Популярен
Ранг: Популярен

Регистриран на: Пон Мар 22, 2010 8:52 pm
Мнения: 328
Мнение Re: Един CALL до много функции...
Всашност в монета работи точно така. Ама предпочитам предишният метод. Исновната причина да търся друг подход е следната. Цялата ми концепция е на 1мС да ми се изпълняват определени функции. С цел по-ниска консумация си свалям клока. Обаче се оказва, че да сканирам структурата за определено ИД е по-бавно от 1мС.....


Пон Ное 18, 2013 12:01 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11266
Местоположение: Добрич
Мнение Re: Един CALL до много функции...
Vesko написа:

Вариантите да си изграждам опашки или статични масиви с функции, който трябва да викам не ми харесва. Тогава като даден файл го махна от компилацията, някой трябва да се погрижи да го махне от статичният списък...


Ма кой ти каза да правиш статични... аз предложих динамичен масив/списък. Който иска да получава нотификации си се регистрира сам. Като му махнеш сорса няма кой да го вкара в списъка.


Пон Ное 18, 2013 12:11 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Окт 11, 2011 11:53 pm
Мнения: 4582
Местоположение: Brussels / Пловдив
Мнение Re: Един CALL до много функции...
miro_atc написа:
Vesko написа:

Вариантите да си изграждам опашки или статични масиви с функции, който трябва да викам не ми харесва. Тогава като даден файл го махна от компилацията, някой трябва да се погрижи да го махне от статичният списък...


Ма кой ти каза да правиш статични... аз предложих динамичен масив/списък. Който иска да получава нотификации си се регистрира сам. Като му махнеш сорса няма кой да го вкара в списъка.

За да се регистрира сам пак трябва някой да го извика ... т.е. стигаш до същия проблем.

Веско, ако паметта не е проблем за да ускориш изпълнението може да си направиш някакъв кеш. Но при всички случаи си е простотия - нещо може ли да се свърши компиле тайм не трябва да се прави рън тайм. По скоро виж за някакъв твой си препроцесор който да анализира сорсовете и да подготвя линкерския скрипт - едно допълнително изискване в мейкфайла и всичко ще работи автоматично.

_________________
Мразя да мразя ...


Пон Ное 18, 2013 12:23 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Окт 11, 2011 11:53 pm
Мнения: 4582
Местоположение: Brussels / Пловдив
Мнение Re: Един CALL до много функции...
Vesko написа:
Всашност в монета работи точно така. Ама предпочитам предишният метод. Исновната причина да търся друг подход е следната. Цялата ми концепция е на 1мС да ми се изпълняват определени функции. С цел по-ниска консумация си свалям клока. Обаче се оказва, че да сканирам структурата за определено ИД е по-бавно от 1мС.....

Предполагам си се сетил и сам, ама все пак да обърна внимание. Не знам колко е намаления клок, нито броя на фунцкиите за този броадкаст, но 1мс си е доста време - дали не се бавиш прекалено много в някоя от функциите? Тогава каквито и хватки да правиш няма да паднеш под 1мс. Вземи му пусни някакъв профайлър да видиш къде колко се баву. Така като те слушам правиш нещо с микроконтролер - за да не си разбутваш кода с външен профайлър, клати един пин във всяка итерация на този цикъл, запиши го с един логически анализатор и виж после има ли нещо съмнително. Клатенето на пина трябва да е 1-2 инструкции, така че няма съществено да изкриви времената.

_________________
Мразя да мразя ...


Пон Ное 18, 2013 12:34 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11266
Местоположение: Добрич
Мнение Re: Един CALL до много функции...
palavrov написа:
За да се регистрира сам пак трябва някой да го извика ... т.е. стигаш до същия проблем.


При Ц++ се викат конструкторите на всички статични (разбирай глобални) обекти ;-)

верно пак по същия начин чрез секции, но поне е стандартно и се предполага че *вече* е направено за всяка Ц++ система.


Пон Ное 18, 2013 12:35 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Окт 11, 2011 11:53 pm
Мнения: 4582
Местоположение: Brussels / Пловдив
Мнение Re: Един CALL до много функции...
miro_atc написа:
При Ц++ се викат конструкторите на всички статични (разбирай глобални) обекти ;-)

верно пак по същия начин чрез секции, но поне е стандартно и се предполага че *вече* е направено за всяка Ц++ система.

Ц++ не е хубаво решение точно за такива проблеми, верно че конструкторите на статичните обекти се викат автоматично и само толкова. В момента в който ти потрябва нещо по засукано и си дотам - например не може да контролираш реда в който ще се извикат а това не е без значение - концептуално не е измислено, решението е пак със специфични хватки. Не се заяждам - просто според мен ако проблема може да се реши на чисто Ц няма смисъл да се ползва Ц++ - само се утежнява кода.

_________________
Мразя да мразя ...


Пон Ное 18, 2013 12:44 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11266
Местоположение: Добрич
Мнение Re: Един CALL до много функции...
Ми аз вече казах, че на чисто Ц няма чисто решение ;-)

Ц++ има всички възможности на Ц плюс още, включително ако щеш и за реда на инициализациите има.

А това че утежнявал кода са пълни глупости, напротив точно обратното е, особено ако ползваш шаблони и ги ползваш разумно.


Пон Ное 18, 2013 12:56 am
Профил
Ранг: Популярен
Ранг: Популярен

Регистриран на: Пон Мар 22, 2010 8:52 pm
Мнения: 328
Мнение Re: Един CALL до много функции...
На чисто Ц има __attribute__((constructor)) и се извикват преди мейна. Ако разширението на GCC може да се приеме за чисто Ц. Така че вариянта с регистрацията си остава, но заема РАМ. А клока, като го сваля под 2МХц не успявам да си завътя цикъла да викам един броадкаст през таблица (която сканирам линейноза определено ИД) и на влизам през 1милисек в прекъсване (и на всяко прекъсване се викат неизвесно колко функции). Може би заради оследното ми е проблема, те всъщност не съм сигурен, че ми трябват точно в този момент....


Пон Ное 18, 2013 7:38 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Окт 11, 2011 11:53 pm
Мнения: 4582
Местоположение: Brussels / Пловдив
Мнение Re: Един CALL до много функции...
miro_atc написа:
Ми аз вече казах, че на чисто Ц няма чисто решение ;-)

Ц++ има всички възможности на Ц плюс още, включително ако щеш и за реда на инициализациите има.

А това че утежнявал кода са пълни глупости, напротив точно обратното е, особено ако ползваш шаблони и ги ползваш разумно.

Я дай пример как се променя реда на инициализация? Аз не знам за такъв и ми е любопитно :)
С Ц++ не се занимавам доста време и съм спрял да следя какви новости има по него.

За утежняването - утежняване е когато за да се свърши дадена работа трябва да се изпише повече сорс или да се изпълни повече код.
Решението на Веско е в 15-на реда - виж колко ще излезе на Ц++ :)

_________________
Мразя да мразя ...


Пон Ное 18, 2013 10:26 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Мар 13, 2006 1:59 pm
Мнения: 3867
Местоположение: Габрово
Мнение Re: Един CALL до много функции...
Защо не помислиш от друга гледна точка - да ускориш викането. Имам предвид че това търсене на ИД в таблица е бабешки метод, организирай си (някакво подобие на) лист и си ги викай. Предполагам че ускоряването на търсенето примерно 10 пъти ще ти реши проблема директно.
Ако искаш някаква гъвкавост можеш да го направиш и на pre-build стъпка, нещо като код генератор. Слагаш в публичния хедър на разните компоненти един define/macro с типа на event-а и посветената функция за извикване (callback-а). После обиколи си хедърите/сорсовете и извади тия декларация, генерирай сорса който да ти ги вика и си готов. Цялата тая работа трябва да се свърши от скрипт някакъв, разбира се.

Генерално проблемът ти не ми е много чист- добавяйки код (модул, компонент) в някакъв проект иска да го "интегрираш". Такова интегриране реално се описва с таблицата кои функции на кое събитие да се викат. Най-малкото трябва да създадеш инстанция от тоя код (конструктора). Като се съгласиш че това е необходимо, ще видиш че има много начини да направиш "интеграцията" тръгвайки от там. Визирам инстанцията на компонента при създаването си извършва регистрация за дадени събития, които я вълнуват (publish-subscribe).

Ако искаш да е само build time, имплементацията ти на publish-subscribe почва да работи със статична таблица. Тая таблица обикновено е масив или списък от списъци. Как да вкараш описанието на новия ти модул в тази таблица? Или ръчно (ти го описваш някъде), или със скрипт който търси нещо специфично. Или задавайки конструктор в c++.

И друго нещо базово - постановката с "нисък клок" и "polling на 1мс" обикновено е много далеко от power-efficient код.


Едит: те колегите пуснали повечето от нещата вече. Като бележка през линкера няма да можеш да направиш функциите inline. Което е възможно ако го направиш с код генератор.


Пон Ное 18, 2013 10:29 am
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 37 мнения ]  Отиди на страница 1, 2, 3  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 1 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни