OKF писал(а):Почти всегда всё накрученное можно оформить функцией (если надо положить отдельным файлом), расписать и забыть
а мусор можно под ковёр замести... и забыть. не мой подход, хотя, чего там скрывать - приходится так делать порой...
ПростоНуб писал(а):Просьба сильно не пинать
да когда ж такое было, чтобы за попытку помочь пинали?!

однако, в вашем подходе, помимо относительной сложности и некоторой загадочности, есть еще одна проблема: сортировка "образцов". это затрудняет процесс модификации списка вручную.
вот смотрите, как сделал сейчас я (не в плане критики вашего варианта, а вообще в плане поедлиться опытом).
слегка подправил скрипт линкера так, чтобы он обрабатывал секцию ".my_table", размещая её в PROGMEM, и заодно определил два символа - начало этой секции и конец. сделал макрос, который по заданному шаблону генерирует объявление строковой константы (в секции .my_table), задающей принятое уведомление, и функции для обработки этого уведомления. в коде написал небольшую функцию с циклом, который от адреса "начало секции my_table" до ареса "конец секции my_table" перебирает строки и сравнивает их с принятой строкой от модема, и, если совпадение обнаружено, вызывает соответствующую функцию обработки.
а теперь - внимание! что это мне дает: в любом месте своего кода при помощи макроса я объявляю функцию-обработчик уведомления, и не забочусь ни о том, чтобы править какие-то массивы строк, контролировать размерность этих массивов и т.п. - все делается автоматически! не нужен более обработчик - удаляю его в том месте, где объявил, и снова ни о чем не переживаю.
кстати, аналогично сделал и программные таймеры. в плане удобства - просто очень шикарно, рекомендую всем!
вот так это выглядит в коде:
Код: Выделить всё
/// определение функции обработки команды s
#define CMD_HOOK(s) static const __flash char s [] = "+" # s ; \
static void CONCAT(hook_, s)(FUNC_PARAM); \
static const tbl_item_t __attribute__((used, section(".my_table"))) CONCAT(item_, s) = {.cmd = s, .func = CONCAT(hook_, s)}; \
static void CONCAT(hook_, s)(FUNC_PARAM)
↑ это макрос, задающий сразу строку-шаблон и функцию-обработчик ↑
Код: Выделить всё
void gsm_str_process(char *str){
extern const int __my_tbl_start;
extern const int __my_tbl_end;
const __flash tbl_item_t *item = (void*)&__my_tbl_start;
// начиная с первого зарегистрированного обработчика и до последнего
for(; item != (void*)&__my_tbl_end; item++){
// если зарегистрирован обработчик-пустышка - игнорируем его
if(item->func == NULL) continue;
// если команда найдена
if(respcmp(item->cmd, str)){
// вызываем обработчик и завершаем перебор
item->func(str, item);
return;
}
}
debug_prn(PSTR("Unknown EVENT: \"%s\""), str);
}
↑ это функция поиска в полученной строке совпадения с одним из шаблонов и вызов соответствующего обработчика ↑
Код: Выделить всё
CMD_HOOK(CMTI){
uint16_t n;
// str = +CMTI: "SM", N
char *begin = find_chr(str,',',1);
if(begin){
n = atoi(begin);
put_message(MAIN_MSG_QUEUE, MSG_SYS, SYS_SMS, n);
}
}
↑ а вот так выглядит один из обработчиков, конкретно этот - уведомление о приходе СМС "
+CMTI" ↑
наконец, вот такой кусочек добавлен в скрипт линкера, чтобы все это заработало:
Код: Выделить всё
/* Внедрение моих секций для таблиц */
__my_tbl_start = . ;
*(.my_table)
*(.my_table*)
KEEP (*(.my_table))
__my_tbl_end = . ;
KEEP (SORT(*)(.my_table))
/* Конец моих секций для таблиц */
/* From this point on, we don't bother about wether the insns are
below or above the 16 bits boundary. */
*(.init0) /* Start here after reset. */
KEEP (*(.init0))
*(.init1)
специально показал несколько строк оригинального скрипта (в конце), чтобы можно было понять, в какое место добавлял (конкретно - в секцию text).
возможно, кто-нибудь возьмёт на вооружение
