Си. Передача массива констант в функцию, хранение и вызовы

Обсуждаем контроллеры компании Atmel.
RealHann
Открыл глаза
Сообщения: 55
Зарегистрирован: Ср май 14, 2014 15:46:02
Откуда: Харьков

Си. Передача массива констант в функцию, хранение и вызовы

Сообщение RealHann »

Всем доброго вечера!
Запнулся на проблеме. Нид хэлп, как говорится )
Задача.
Есть ядро программы в виде отдельного модуля. Назвал его Kernel
К проекту подключаются другие сишные модули. Они автоматически регистрируются в ядре.
У каждого модуля есть такая запись:

Код: Выделить всё

#define  _NoPSR  0

static const uint16_t* PSR_Addresses[]
{
	//InitPSR
	_NoPSR,
	//TurnOnPSR
	_NoPSR,
	//TurnOffPSR
	_NoPSR,
	//ReportPRS
	(uint16_t*) &ExceptionsReport,
	//ProcessPRS
	(uint16_t*) &Exceptions,
	
	//Input 1 - Очистка таблицы исключений
	(uint16_t*) &RemoveExceptions
};
Вначале идут стандартные функции, потом неопределенное количество Input'ов, которые зависят от конкретного модуля. Если функция не описана - там стоит _NoPSR, т.е. 0. Обработчик в ядре вызов не выполнит.

Далее, при инициализации каждого модуля, последний заносит в общую таблицу ядра некую информацию о себе, в том числе он должен передать указатель на эту таблицу. Вроде такого:

Код: Выделить всё

#define Sub (uint16_t*) &

void Exceptions_KernelInit(void)
{
	Kernel_RegisterProcess(Sub InsExceptions, PSR_Addresses, _DT_Exception);
}
В ядре эта информация сохраняется в структуре:

Код: Выделить всё

struct
{
	enum _dtList EDType;
	uint16_t (*pFunc);
	uint16_t PSRtable;   //тут пока глюки
} knAddr[ProcessesCount];

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) произвести вызов.
По-русски хоть написал? ))
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение ARV »

ну а проблема-то в чем?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
RealHann
Открыл глаза
Сообщения: 55
Зарегистрирован: Ср май 14, 2014 15:46:02
Откуда: Харьков

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение RealHann »

А вот не работает ) В генах, походу )) слабенький я еще в Си
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение ARV »

что не работает-то? вы своего Гену там приструните, пусть толком говорит
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение Аlex »

Когда "не работает", самое эффективное - подключать инструменты отладки. Только Вы, как автор кода, сможете найти проблему в нём.
Реклама
RealHann
Открыл глаза
Сообщения: 55
Зарегистрирован: Ср май 14, 2014 15:46:02
Откуда: Харьков

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение RealHann »

Для начала я не могу передать в функцию указатель на массив констант неопределенной длины.
Где-то косяк. Или несколько.
Когда в последней строке
return ((char(*)(void)) ...что-то тут... (knAddr[DeviceID].PSRtable)[_kp_position]();
формируется адрес вызываемой функции, там всегда бред в итоге. Бросок в гущу кода.

Добавлено after 58 seconds:
[uquote="Аlex",url="/forum/viewtopic.php?p=3117011#p3117011"]Когда "не работает", самое эффективное - подключать инструменты отладки. Только Вы, как автор кода, сможете найти проблему в нём.[/uquote]

так-то оно так. только знаний пока маловато. и опыта. а спросить не у кого
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение ARV »

рекомендую избавиться от явного приведения типов указателей - сразу делайте указатели нужного типа, иначе можно напортачить.
массивы "неопределенной длины" - это очень хороший способ выстрелить себе в ногу... источник всех проблем в ОС, напиманных на Си - зачем это вам?

и, если честно, я не очень понял, что вы затеяли... я подорбную систему "модулей" делал так:
1. определил структуру, описывающую интерфейс модуля
2. в каждом модуле структура эта помещена во flash и заполнена адресами соответствующих функций. если функция модулем не поддерживается, там пишу NULL
3. при "регистрации" модуля адрес этой структуры передаю "менеджеру" модулей, а он заносит этот адрес в массив.
4. когда надо обратиться к модулю, то по массиву беру нужную структуру, а из нее - адрес функции...
вот и все. у вас так или не так?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
RealHann
Открыл глаза
Сообщения: 55
Зарегистрирован: Ср май 14, 2014 15:46:02
Откуда: Харьков

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение RealHann »

Так, только не определено количество этих функций. У каждого подключаемого модуля оно может быть разным. Ваша реализация это может поддержать?
Глобально идея выглядит так. Попробую вкратце.
Берется новая плата. На ней, к примеру, есть пять светодиодов, три кнопки и какой-то интерфейс связи (пусть будет уарт).
Текст программы 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: Си. Передача массива констант в функцию, хранение и вызовы
Можете дать пример кода, где описывается ваша структура во флэш?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение ARV »

Код для AVR-GCC не хуже версии 4

Это от незавершенного проекта "цифровой цветомузыки" :)
Вложения
main_effect.h
Здесь определены все необходимые для работы с модулем структуры и т.п.
(3.73 КБ) 324 скачивания
template_effect.c
Это "шаблон" модуля - все функции в виде пустышек.
(2.1 КБ) 631 скачивание
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
RealHann
Открыл глаза
Сообщения: 55
Зарегистрирован: Ср май 14, 2014 15:46:02
Откуда: Харьков

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение RealHann »

спасибо! завтра поковыряюсь
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение ARV »

Что касается неизвестного количества функций у модуля, то могу предложить такой вариант

Код: Выделить всё

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: Си. Передача массива констант в функцию, хранение и вызовы
да, чуть не забыл: инициализировать структуру интерфейса модуля можно так:

Код: Выделить всё

static module_interface_t module = {
   .func_cnt = 3,
   .interface[0] = func1,
   .interface[1] = func2,
   .interface[2] = func3
};
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
RealHann
Открыл глаза
Сообщения: 55
Зарегистрирован: Ср май 14, 2014 15:46:02
Откуда: Харьков

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение RealHann »

День добрый!
Получается так.

Код: Выделить всё

typedef int (*interface_func);	//(char *ptr); // определили тип для интерфейсной функции

// определяем тип для описания интерфейса модуля
typedef struct{
	uint8_t func_cnt; // количество функций в интерфейсе
	interface_func tfunc;
	interface_func interface[]; // массив неопределенной длины
} module_interface_t;
в модуле

Код: Выделить всё

static module_interface_t Addresses = {
	.func_cnt = 3,
	.interface[0] = ExceptionsReport,     //<< Error: expected primary-expression before '.' token
        .interface[1] = Exceptions,     //<< Error: expected primary-expression before '.' token
	.interface[2] = RemoveExceptions,     //<< Error: expected primary-expression before '.' token
	.tfunc = RemoveExceptions
};
т.е. там где идет присвоение массиву - не хочет компилировать
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение ARV »

А почему у вас тип указателя на функцию без круглых скобок?

кроме того, обращаю ваше внимание, что приведенная мною форма инициализации поддерживается AVR-GCC c включенной поддержкой C99 и расширений GNU, другие компиляторы могу так сразу не прожевать...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
RealHann
Открыл глаза
Сообщения: 55
Зарегистрирован: Ср май 14, 2014 15:46:02
Откуда: Харьков

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение RealHann »

вот этот и не жует. я в AtmelStudio7 пишу. проект под C++. Облом, значиццо. Буду думать
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение ARV »

Должен жевать, добавьте опцию -std=gnu99

И всё-таки, почему указатель на функцию у вас без круглых скобок? вместо typedef int (*interface_func); должно быть typedef int (*interface_func)(void); или с нужными типами параметров...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
RealHann
Открыл глаза
Сообщения: 55
Зарегистрирован: Ср май 14, 2014 15:46:02
Откуда: Харьков

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение RealHann »

А. этот недочет я исправил сразу. спасибо.
а параметр -std=gnu99 не хочет спасать ситуацию

Добавлено after 2 hours 16 minutes 37 seconds:
Re: Си. Передача массива констант в функцию, хранение и вызовы
Перенес процесс присвоения адресов в отдельную функцию и все заработало!
Спасибо за помощь!
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение ARV »

RealHann писал(а):Перенес процесс присвоения адресов в отдельную функцию и все заработало!
это как?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
RealHann
Открыл глаза
Сообщения: 55
Зарегистрирован: Ср май 14, 2014 15:46:02
Откуда: Харьков

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение RealHann »

Код: Выделить всё

#define Sub (uint16_t*) &

static module_interface_t DeviceInfo;

void Exceptions_KernelInit(void)
{
	DeviceInfo.interface[_kp_ProcessPSR] = Sub Exceptions;
	DeviceInfo.interface[_kp_ReportPSR] = Sub ExceptionsReport;
	DeviceInfo.interface[_kp_InputPSR + 0] = Sub RemoveExceptions;

	Kernel_RegisterProcess(Sub InsExceptions, &DeviceInfo, _DT_Exceptions);
}
ну, и сам вызов потом:

Код: Выделить всё

char Kernel_CallPSR(char DeviceID, char _kp_position)
{
	module_interface_t *DevInfo = knAddr[DeviceID].DeviceInfo;
	uint16_t* funcAddr = (uint16_t*) DevInfo->interface[_kp_position];

	if ((uint16_t) funcAddr == _NoPSR)
		return 0;
	else
		return ((char(*)(void)) funcAddr)();
}
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение ARV »

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

Мой уютный бложик... заходите!
RealHann
Открыл глаза
Сообщения: 55
Зарегистрирован: Ср май 14, 2014 15:46:02
Откуда: Харьков

Re: Си. Передача массива констант в функцию, хранение и вызо

Сообщение RealHann »

в .hpp

Код: Выделить всё

typedef uint16_t (*interface_func);	// определили тип для интерфейсной функции

// определяем тип для описания интерфейса модуля
struct module_interface_t
{
	char func_cnt; // количество функций в интерфейсе
	interface_func interface[]; // массив неопределенной длины
};
Добавлено after 1 minute 13 seconds:
Re: Си. Передача массива констант в функцию, хранение и вызовы
Ваши комментарии так и пойдут в мир )
Ответить

Вернуться в «AVR»