jenya7 0 September 2, 2020 Posted September 2, 2020 · Report post У меня сейчас вся инициализация периферии в самом таске 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(;;){} } Quote Share this post Link to post Share on other sites More sharing options...
aaarrr 72 September 2, 2020 Posted September 2, 2020 · Report post 6 minutes ago, jenya7 said: может вынести инициализацию из таска? Лучше сделать отдельную задачу, которая: 1. Проинициализирует периферию 2. Запустит остальные задачи 3. Самоубьётся Quote Share this post Link to post Share on other sites More sharing options...
SMaster 0 September 2, 2020 Posted September 2, 2020 · Report post ИМХО, правильно можно так и так: 1. Если в задаче инициализируется только та периферия, которую обслуживает данная задача, тогда можно и в начале задачи это делать. Где-то читал, что в случае, если в инициализации используются системные вызовы, рекомендуется делать так: void task1(void * param) { while (1) { periph_init(); while (1) { periph_routine(); } } } Мол компилятор без первого цикла (хоть он и не нужен) может криво оптимизировать и будет бо-бо. 2. Лично я предпочитаю все инициализации делать в одном месте, как в вашем втором случае. Quote Share this post Link to post Share on other sites More sharing options...
haker_fox 168 September 2, 2020 Posted September 2, 2020 · Report post 41 minutes ago, jenya7 said: может вынести инициализацию из таска? Да, лучше вынести и разбить на функции по назначению: инициализация дисплея, памяти, интерфейсов и т.п.. Ибо трудно читать такие огромные портянки) Инициализировать в одной задаче, которую затем удалить. Впрочем, я также инициализирую периферию по "месту требования": т.е. в том файле, где эта периферия нужна. Драйвера периферии не позволяют инициализировать её повторно, поэтому коллизий не возникает. 23 minutes ago, SMaster said: Мол компилятор без первого цикла (хоть он и не нужен) может криво оптимизировать и будет бо-бо. А можно подробнее? Это же обыкновенная функция. Делаю без первого цикла, и всё работает. Quote Share this post Link to post Share on other sites More sharing options...
jenya7 0 September 2, 2020 Posted September 2, 2020 · Report post 1 hour ago, aaarrr said: Лучше сделать отдельную задачу, которая: 1. Проинициализирует периферию 2. Запустит остальные задачи 3. Самоубьётся фига се. такого решения я не встречал. Quote Share this post Link to post Share on other sites More sharing options...
SMaster 0 September 2, 2020 Posted September 2, 2020 · Report post 20 minutes ago, haker_fox said: А можно подробнее? Это же обыкновенная функция. Делаю без первого цикла, и всё работает. Да, действительно, для FreeRTOS вряд ли так надо делать. Встречал данную рекомендацию для старенькой jacOS (вот буквально только что нашел ее в доках от этой РТОС). Но там совсем другая история: это кооперативная ОС + IAR вытворял чудеса компиляции, возможно вызванные недоработками самой ОС. Сорри, ляпнул "рекомендацию" не подумав. :) Quote Share this post Link to post Share on other sites More sharing options...
haker_fox 168 September 2, 2020 Posted September 2, 2020 · Report post 3 minutes ago, SMaster said: для старенькой jacOS Оооо, так это же начало 2000-х, как помню) Тогда и компиляторы могли "глючить". Тот же IAR. Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 359 September 2, 2020 Posted September 2, 2020 · Report post У меня периферия, требующая первостепенной инициализации (отладочный 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(), в которой можно было инициализировать железо. Но, ИМХО, это не всегда удобно. Quote Share this post Link to post Share on other sites More sharing options...
SMaster 0 September 2, 2020 Posted September 2, 2020 · Report post 25 minutes ago, haker_fox said: Оооо, так это же начало 2000-х, как помню) Тогда и компиляторы могли "глючить". Тот же IAR. Для меня это была вторая половина 2000х :) Пару-тройку лет назад надо было подновить проект тех времен. И тут я удивился: в АТМега16 1 кБ RAM. Рили? Казалось, что больше. И как-то ведь работает. :) Сорри за офтоп, нахлынули воспоминания. :) 4 minutes ago, Arlleex said: Они в xPortStartSheduler() вставляли вызов пользовательской функции vApplicationSetupHardware(), в которой можно было инициализировать железо. Такой костыль несложно и самому добавить. :) В общем-то не страшно и последовательно вызвать vApplicationSetupHardware(), а затем xPortStartSheduler(). :) Quote Share this post Link to post Share on other sites More sharing options...
aaarrr 72 September 2, 2020 Posted September 2, 2020 · Report post 1 hour ago, jenya7 said: такого решения я не встречал. Между тем, это правильное решение: так появляется возможность пользоваться средствами ОС при инициализации периферии. Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 359 September 2, 2020 Posted September 2, 2020 · Report post 2 минуты назад, SMaster сказал: В общем-то не страшно и последовательно вызвать vApplicationSetupHardware(), а затем xPortStartSheduler(). Вроде как, единственное, что гарантировалось в той функции, так это запрещенные прерывания на момент входа в нее. Так что, по сути, запрещаем прерывания, настраиваем периферию, разрешаем прерывания (глобальные) - и вот он, тот же результат. Quote Share this post Link to post Share on other sites More sharing options...
haker_fox 168 September 2, 2020 Posted September 2, 2020 · Report post 40 minutes ago, aaarrr said: Между тем, это правильное решение Делал раньше точно так, как вы указали выше. Но консольку, хотя бы на вывод, иногда полезно настроить и до старта ОС. По-крайней мере иметь возможность заставить драйвер последовательного порта поработать без окружения ОС. 42 minutes ago, Arlleex said: так это запрещенные прерывания на момент входа в нее. О как. А заче запрещать прерывания для конфигурации периферии? Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 359 September 2, 2020 Posted September 2, 2020 · Report post 5 минут назад, haker_fox сказал: О как. А заче запрещать прерывания для конфигурации периферии? Чтобы какой-нибудь GiveFromISR() не ввел еще не запущенный диспетчер в ступор. Или, например, в обработчике прерывания вызывается API RTOS выдачи семафора. А этот семафор еще не выделился в памяти (не был вызван CreateSemaphore()). Quote Share this post Link to post Share on other sites More sharing options...
jcxz 378 September 2, 2020 Posted September 2, 2020 · Report post 6 часов назад, aaarrr сказал: 3. Самоубьётся А это то зачем? 3 часа назад, Arlleex сказал: А этот семафор еще не выделился в памяти (не был вызван CreateSemaphore()). Так вообще то, по уму, сначала делается инит всех переменных драйвера(-ов) в ОЗУ, и только затем - инит периферии, использующей эти переменные. Если эти переменные (в том числе и средства синхронизации ОС) используются как семафоры разделяемой периферии, то ининтить их можно сразу в состояние "занято". А уже код инициализации периферии, по завершении своей работы, переведёт их в "свободно". Quote Share this post Link to post Share on other sites More sharing options...
aaarrr 72 September 2, 2020 Posted September 2, 2020 · Report post 13 minutes ago, jcxz said: А это то зачем? За ненадобностью. Можно и не убивать, если придумать ей разумное занятие. Quote Share this post Link to post Share on other sites More sharing options...