jenya7 0 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба У меня сейчас вся инициализация периферии в самом таске void operation_task() { static int mflag = 0; uint16_t message_status = 0; CFG_CONFIG_SetVal(); /* PBIT process */ power_init(); WAIT1_Waitms(100); /* SET config. value for FPGA */ err_dat = init_configuration(); /* detection of mode by discrete : Maintenance or Operational */ g_crt_state = mode_detection_by_discrete(); //includes import parameters from flash err_dat |= pbit_process(); DrawTestDisplay(); WAIT1_Waitms(500); ClearDisplay(); MENU_Setup(); ResetGlobalVariables(); LIGHT_ImportDimParam(); //////////////////LOGGER///////////////////// NFLASH_Reset(); nand_flash_status = NFLASH_Init(); LOG_ReadPartitionData(&logger_data); ImportBadBlocksData(); Call_1553(); mcp_init(); incoming_mailboxes_init(); while(1) { WDog1_Clear(); if(mflag == 0) { operation_maint_process(); message_status = MM_check_new_message(); if (message_status > 1) err_count_1553++; } if(msgFlag == 1) { msgFlag = 0; mflag = dispecth_UART_cmd(); } } } int main(void) { rtos_stat = FRTOS1_xTaskCreate((TaskFunction_t)operation_task, (signed char*) "oper_task", /*2048*/ 2048, NULL, 2, NULL); PEX_RTOS_START(); for(;;){} } может вынести инициализацию из таска? void operation_task() { while(1) { WDog1_Clear(); if(mflag == 0) { operation_maint_process(); message_status = MM_check_new_message(); if (message_status > 1) err_count_1553++; } if(msgFlag == 1) { msgFlag = 0; mflag = dispecth_UART_cmd(); } } } int main(void) { static int mflag = 0; uint16_t message_status = 0; CFG_CONFIG_SetVal(); power_init(); WAIT1_Waitms(100); err_dat = init_configuration(); g_crt_state = mode_detection_by_discrete(); err_dat |= pbit_process(); DrawTestDisplay(); WAIT1_Waitms(500); ClearDisplay(); MENU_Setup(); ResetGlobalVariables(); LIGHT_ImportDimParam(); //////////////////LOGGER///////////////////// NFLASH_Reset(); nand_flash_status = NFLASH_Init(); LOG_ReadPartitionData(&logger_data); ImportBadBlocksData(); Call_1553(); mcp_init(); incoming_mailboxes_init(); rtos_stat = FRTOS1_xTaskCreate((TaskFunction_t)operation_task, (signed char*) "oper_task", 2048, NULL, 2, NULL); PEX_RTOS_START(); for(;;){} } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба 6 minutes ago, jenya7 said: может вынести инициализацию из таска? Лучше сделать отдельную задачу, которая: 1. Проинициализирует периферию 2. Запустит остальные задачи 3. Самоубьётся Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SMaster 0 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба ИМХО, правильно можно так и так: 1. Если в задаче инициализируется только та периферия, которую обслуживает данная задача, тогда можно и в начале задачи это делать. Где-то читал, что в случае, если в инициализации используются системные вызовы, рекомендуется делать так: void task1(void * param) { while (1) { periph_init(); while (1) { periph_routine(); } } } Мол компилятор без первого цикла (хоть он и не нужен) может криво оптимизировать и будет бо-бо. 2. Лично я предпочитаю все инициализации делать в одном месте, как в вашем втором случае. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба 41 minutes ago, jenya7 said: может вынести инициализацию из таска? Да, лучше вынести и разбить на функции по назначению: инициализация дисплея, памяти, интерфейсов и т.п.. Ибо трудно читать такие огромные портянки) Инициализировать в одной задаче, которую затем удалить. Впрочем, я также инициализирую периферию по "месту требования": т.е. в том файле, где эта периферия нужна. Драйвера периферии не позволяют инициализировать её повторно, поэтому коллизий не возникает. 23 minutes ago, SMaster said: Мол компилятор без первого цикла (хоть он и не нужен) может криво оптимизировать и будет бо-бо. А можно подробнее? Это же обыкновенная функция. Делаю без первого цикла, и всё работает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба 1 hour ago, aaarrr said: Лучше сделать отдельную задачу, которая: 1. Проинициализирует периферию 2. Запустит остальные задачи 3. Самоубьётся фига се. такого решения я не встречал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SMaster 0 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба 20 minutes ago, haker_fox said: А можно подробнее? Это же обыкновенная функция. Делаю без первого цикла, и всё работает. Да, действительно, для FreeRTOS вряд ли так надо делать. Встречал данную рекомендацию для старенькой jacOS (вот буквально только что нашел ее в доках от этой РТОС). Но там совсем другая история: это кооперативная ОС + IAR вытворял чудеса компиляции, возможно вызванные недоработками самой ОС. Сорри, ляпнул "рекомендацию" не подумав. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба 3 minutes ago, SMaster said: для старенькой jacOS Оооо, так это же начало 2000-х, как помню) Тогда и компиляторы могли "глючить". Тот же IAR. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба У меня периферия, требующая первостепенной инициализации (отладочный UART, например), настраивается перед запуском всех задач. Т.е. в main() есть некая функция InitDevDrv(), которая настраивает периферию первой необходимости и периферию общего назначения. Периферия общего назначения это, например, какие-нибудь GPIO для реле, дискретных входов/выходов и т.д. Их драйверы не обслуживают какую-то конкретную задачу, они лишь предоставляют некий сервисный API любому желающему процессу. А вот уже конкретная периферия под конкретный программный модуль настраивается в самой задаче перед while(1) или около того. Вот, к примеру, main() Скрытый текст #include "main.h" #include "pcdbg.h" #include "gbctl.h" #include "canctl.h" #include "sysctl.h" #include "eds.h" #include "hw.h" #include "wdt.h" #include "dbg.h" #include "led.h" #include "pwr.h" #include "nvm.h" static void InitDevDrv(void) { wdt_InitExt(); wdt_UpdAll(); dbg_Init(); led_Init(); pwr_Init(); nvm_Init(); } static void ActAftSysRst(void) { if(hw_isRstOnPwr()) SysCtlInf.rstonpwr = 1, dbg_PrintWarn("Reset on 'PWR'"); else if(hw_isRstOnSoft()) dbg_PrintWarn("Reset on 'SOFT'"); else if(hw_isRstOnIWDT()) dbg_PrintCrit("Reset on 'Int. WDT'"); else if(hw_isRstOnExtWDT()) dbg_PrintCrit("Reset on 'Ext. WDT'"); hw_ClrRstInf(); dbg_PrintNorm("System start"); } static void RunUsrApp(void) { pcdbg_Init(); gbctl_Init(); canctl_Init(); sysctl_Init(); } int main(void) { InitDevDrv(); ActAftSysRst(); RunUsrApp(); eds_RunTskManager(); return 1; } P.S. Вот тут движок форума создает пустую строку, которую невозможно удалить и которая режет глаза... а это, например, функция инициализации модуля взаимодействия по CAN Скрытый текст ... void canctl_Init(void) { can_Init(); eds_CreateTsk(EDS_TSKID_CANCTL, CANCtlTsk, 256); } У Xilinx, например, был небольшой костыль в исходниках FreeRTOS, которую они поставляли с Vivado SDK. Они в xPortStartSheduler() вставляли вызов пользовательской функции vApplicationSetupHardware(), в которой можно было инициализировать железо. Но, ИМХО, это не всегда удобно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SMaster 0 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба 25 minutes ago, haker_fox said: Оооо, так это же начало 2000-х, как помню) Тогда и компиляторы могли "глючить". Тот же IAR. Для меня это была вторая половина 2000х :) Пару-тройку лет назад надо было подновить проект тех времен. И тут я удивился: в АТМега16 1 кБ RAM. Рили? Казалось, что больше. И как-то ведь работает. :) Сорри за офтоп, нахлынули воспоминания. :) 4 minutes ago, Arlleex said: Они в xPortStartSheduler() вставляли вызов пользовательской функции vApplicationSetupHardware(), в которой можно было инициализировать железо. Такой костыль несложно и самому добавить. :) В общем-то не страшно и последовательно вызвать vApplicationSetupHardware(), а затем xPortStartSheduler(). :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба 1 hour ago, jenya7 said: такого решения я не встречал. Между тем, это правильное решение: так появляется возможность пользоваться средствами ОС при инициализации периферии. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба 2 минуты назад, SMaster сказал: В общем-то не страшно и последовательно вызвать vApplicationSetupHardware(), а затем xPortStartSheduler(). Вроде как, единственное, что гарантировалось в той функции, так это запрещенные прерывания на момент входа в нее. Так что, по сути, запрещаем прерывания, настраиваем периферию, разрешаем прерывания (глобальные) - и вот он, тот же результат. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба 40 minutes ago, aaarrr said: Между тем, это правильное решение Делал раньше точно так, как вы указали выше. Но консольку, хотя бы на вывод, иногда полезно настроить и до старта ОС. По-крайней мере иметь возможность заставить драйвер последовательного порта поработать без окружения ОС. 42 minutes ago, Arlleex said: так это запрещенные прерывания на момент входа в нее. О как. А заче запрещать прерывания для конфигурации периферии? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба 5 минут назад, haker_fox сказал: О как. А заче запрещать прерывания для конфигурации периферии? Чтобы какой-нибудь GiveFromISR() не ввел еще не запущенный диспетчер в ступор. Или, например, в обработчике прерывания вызывается API RTOS выдачи семафора. А этот семафор еще не выделился в памяти (не был вызван CreateSemaphore()). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба 6 часов назад, aaarrr сказал: 3. Самоубьётся А это то зачем? 3 часа назад, Arlleex сказал: А этот семафор еще не выделился в памяти (не был вызван CreateSemaphore()). Так вообще то, по уму, сначала делается инит всех переменных драйвера(-ов) в ОЗУ, и только затем - инит периферии, использующей эти переменные. Если эти переменные (в том числе и средства синхронизации ОС) используются как семафоры разделяемой периферии, то ининтить их можно сразу в состояние "занято". А уже код инициализации периферии, по завершении своей работы, переведёт их в "свободно". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 2 сентября, 2020 Опубликовано 2 сентября, 2020 · Жалоба 13 minutes ago, jcxz said: А это то зачем? За ненадобностью. Можно и не убивать, если придумать ей разумное занятие. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться