Всем доброго вечера! Запнулся на проблеме. Нид хэлп, как говорится ) Задача. Есть ядро программы в виде отдельного модуля. Назвал его Kernel К проекту подключаются другие сишные модули. Они автоматически регистрируются в ядре. У каждого модуля есть такая запись:
Вначале идут стандартные функции, потом неопределенное количество Input'ов, которые зависят от конкретного модуля. Если функция не описана - там стоит _NoPSR, т.е. 0. Обработчик в ядре вызов не выполнит.
Далее, при инициализации каждого модуля, последний заносит в общую таблицу ядра некую информацию о себе, в том числе он должен передать указатель на эту таблицу. Вроде такого:
void Kernel_RegisterProcess(uint16_t (*ProcessVector), const uint16_t *PSRtable, enum _dtList EDType) { knAddr[++knProperties.CurrentID].EDType = EDType; knAddr[knProperties.CurrentID].pFunc = &(*ProcessVector); knAddr[knProperties.CurrentID].PSRtable = (uint16_t) &(*PSRtable); //глюки-глюки. сюда пока особо не смотреть. игрался, ничего не выходит пока }
//И дальше должен идти сам вызов удаленной функции: char Kernel_CallPSR(char DeviceID, char _kp_position) { if ((uint16_t) knAddr[DeviceID].PSRtable[_kp_position] == _NoPSR) return 0; else return ((char(*)(void)) ...что-то тут... (knAddr[DeviceID].PSRtable)[_kp_position](); }
Т.е. механизм такой. Ядро знает где у какого модуля искать таблицу PSR_Addresses[], в которой лежат адреса ее функций. И по номеру нужной функции (_kp_position) произвести вызов. По-русски хоть написал? ))
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Для начала я не могу передать в функцию указатель на массив констант неопределенной длины. Где-то косяк. Или несколько. Когда в последней строке return ((char(*)(void)) ...что-то тут... (knAddr[DeviceID].PSRtable)[_kp_position](); формируется адрес вызываемой функции, там всегда бред в итоге. Бросок в гущу кода.
рекомендую избавиться от явного приведения типов указателей - сразу делайте указатели нужного типа, иначе можно напортачить. массивы "неопределенной длины" - это очень хороший способ выстрелить себе в ногу... источник всех проблем в ОС, напиманных на Си - зачем это вам?
и, если честно, я не очень понял, что вы затеяли... я подорбную систему "модулей" делал так: 1. определил структуру, описывающую интерфейс модуля 2. в каждом модуле структура эта помещена во flash и заполнена адресами соответствующих функций. если функция модулем не поддерживается, там пишу NULL 3. при "регистрации" модуля адрес этой структуры передаю "менеджеру" модулей, а он заносит этот адрес в массив. 4. когда надо обратиться к модулю, то по массиву беру нужную структуру, а из нее - адрес функции... вот и все. у вас так или не так?
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Так, только не определено количество этих функций. У каждого подключаемого модуля оно может быть разным. Ваша реализация это может поддержать? Глобально идея выглядит так. Попробую вкратце. Берется новая плата. На ней, к примеру, есть пять светодиодов, три кнопки и какой-то интерфейс связи (пусть будет уарт). Текст программы main выглядит: void main(void) { Kernel_AddDevice(_DT_Led); Kernel_AddDevice(_DT_Led); Kernel_AddDevice(_DT_Led); Kernel_AddDevice(_DT_Led); Kernel_AddDevice(_DT_Led); Kernel_AddDevice(_DT_Button); Kernel_AddDevice(_DT_Button); Kernel_AddDevice(_DT_Button); Kernel_AddDevice(_DT_UART);
while(1) Kernel; } Все само дальше крутится и отвечает на запросы по UART. Когда приходит пакет по UART, модуль UART передает его ядру, которое ищет у себя нужный адресат и по коду команды вызывает нужную функцию у нужного модуля. Передавая остаток данных пакета тому самому обработчику. Соответственно, у кнопок и светодиода разные задачи и разное количество команд управления (Input'ов у меня). В массив я не могу это засунуть, потому что структура неизвестна. Или я просто не знаю как это организовать правильно?
Добавлено after 12 minutes 35 seconds: Re: Си. Передача массива констант в функцию, хранение и вызовы Можете дать пример кода, где описывается ваша структура во флэш?
Что касается неизвестного количества функций у модуля, то могу предложить такой вариант
Код:
typedef int (*interface_func)(char *ptr); // определили тип для интерфейсной функции
// определяем тип для описания интерфейса модуля typedef struct{ uint8_t func_cnt; // количество функций в интерфейсе interface_func interface[]; // массив неопределенной длины } module_interface_t;
// в менеджере модулей определяем массив, хранящий все модули module_interface_t modules[MAX_MODULE_CNT];
// когда надо обратиться к конкретному модулю, надо делать так: int run_module_func(uint8_t id, uint8_t func_id, char *data){ if(id >= MAX_MODULE_CNT) return -1; // ошибка - модулей меньше, чем указано if(modules[id] == NULL) return -2; // ошибка - модуль с таким номером не зарегистрирован if(func_id >= modules[id].func_cnt) return -3; // ошибка - такая функция не может быть! if(modules[id].interface[func_id] == NULL) return -4; // ошибка - функция не реализована return modules[id].interface[func_id](data); // вызываем функцию и возвращаем ее результат работы }
Добавлено after 6 minutes 57 seconds: Re: Си. Передача массива констант в функцию, хранение и вызовы да, чуть не забыл: инициализировать структуру интерфейса модуля можно так:
typedef int (*interface_func); //(char *ptr); // определили тип для интерфейсной функции
// определяем тип для описания интерфейса модуля typedef struct{ uint8_t func_cnt; // количество функций в интерфейсе interface_func tfunc; interface_func interface[]; // массив неопределенной длины } module_interface_t;
А почему у вас тип указателя на функцию без круглых скобок?
кроме того, обращаю ваше внимание, что приведенная мною форма инициализации поддерживается AVR-GCC c включенной поддержкой C99 и расширений GNU, другие компиляторы могу так сразу не прожевать...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
И всё-таки, почему указатель на функцию у вас без круглых скобок? вместо typedef int (*interface_func); должно быть typedef int (*interface_func)(void); или с нужными типами параметров...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
А. этот недочет я исправил сразу. спасибо. а параметр -std=gnu99 не хочет спасать ситуацию
Добавлено after 2 hours 16 minutes 37 seconds: Re: Си. Передача массива констант в функцию, хранение и вызовы Перенес процесс присвоения адресов в отдельную функцию и все заработало! Спасибо за помощь!
typedef uint16_t (*interface_func); // определили тип для интерфейсной функции
// определяем тип для описания интерфейса модуля struct module_interface_t { char func_cnt; // количество функций в интерфейсе interface_func interface[]; // массив неопределенной длины };
Добавлено after 1 minute 13 seconds: Re: Си. Передача массива констант в функцию, хранение и вызовы Ваши комментарии так и пойдут в мир )
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 68
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения