Перейти к содержанию
    

SergNK

Свой
  • Постов

    138
  • Зарегистрирован

  • Посещение

Весь контент SergNK


  1. TEventFlag.Signal_isr()

    Спасибо за доверие! Первый вариант.
  2. TEventFlag.Signal_isr()

    Можно. Я отладил код под Freescale M0+. Подчистить исходники по комментариям и отступам - и вперёд! Куда сбрасывать и как?
  3. TEventFlag.Signal_isr()

    Удалось-таки победить. Вот что вышло: Это обработчик прерывания для среды IAR: extern "C" void PendSV_Handler() { #if (defined __ARM_ARCH_6M__) // Cortex-M0(+)/Cortex-M1 asm volatile ( " CPSID I \n" // Prevent interruption during context switch " MRS R0, PSP \n" // Load process stack pointer to R0 " SUBS R0, R0, #32 \n" // Adjust R0 to point to top of saved context in stack " MOV R1, R0 \n" // Preserve R0 " MOV R2, R0 \n" // Preserve R0 (needed for os_context_switch_hook() call) " STMIA R1!, {R4-R7} \n" // Save low portion of remaining registers (r4-7) on process stack " MOV R4, R8 \n" // Move high portion of remaining registers (r8-11) to low registers " MOV R5, R9 \n" " MOV R6, R10 \n" " MOV R7, R11 \n" " STMIA R1!, {R4-R7} \n" // Save high portion of remaining registers (r8-11) on process stack : : ); asm volatile ( // At this point, entire context of process has been saved " PUSH {LR} \n" // we must save LR (exc_return value) until exception return " MOV R1, %0 \n" // load os_context_switch_hook() address; " MOV R0, R2 \n" // Restore R0 (needed for os_context_switch_hook() call) " BLX R1 \n" // call os_context_switch_hook(); // R0 is new process SP; " ADDS R0, R0, #16 \n" // Adjust R0 to point to high registers (r8-11) " LDMIA R0!, {R4-R7} \n" // Restore r8-11 from new process stack " MOV R8, R4 \n" // Move restored values to high registers (r8-11) " MOV R9, R5 \n" " MOV R10, R6 \n" " MOV R11, R7 \n" " MSR PSP, R0 \n" // R0 at this point is new process SP " SUBs R0, R0, #32 \n" // Adjust R0 to point to low registers " LDMIA R0!, {R4-R7} \n" // Restore r4-7 " CPSIE I \n" " POP {PC} \n" // Return to saved exc_return. Exception return will restore remaining context : : "r" (os_context_switch_hook) ); #else // #if (defined __ARM_ARCH_6M__) #if (defined __SOFTFP__) // M3/M4 cores without FPU asm volatile ( " CPSID I \n" // Prevent interruption during context switch " MRS R0, PSP \n" // PSP is process stack pointer " STMDB R0!, {R4-R11} \n" // Save remaining regs r4-11 on process stack // At this point, entire context of process has been saved " PUSH {LR} \n" // we must save LR (exc_return value) until exception return " LDR R1, =os_context_switch_hook \n" // call os_context_switch_hook(); " BLX R1 \n" // R0 is new process SP; " LDMIA R0!, {R4-R11} \n" // Restore r4-11 from new process stack " MSR PSP, R0 \n" // Load PSP with new process SP " CPSIE I \n" " POP {PC} \n" // Return to saved exc_return. Exception return will restore remaining context : : ); #else // #if (defined __SOFTFP__) // Core with FPU (cortex-M4F) asm volatile ( " CPSID I \n" // Prevent interruption during context switch " MRS R0, PSP \n" // PSP is process stack pointer " TST LR, #0x10 \n" // exc_return[4]=0? (it means that current process " IT EQ \n" // has active floating point context) " VSTMDBEQ R0!, {S16-S31} \n" // if so - save it. " STMDB R0!, {R4-R11, LR} \n" // save remaining regs r4-11 and LR on process stack // At this point, entire context of process has been saved " LDR R1, =os_context_switch_hook \n" // call os_context_switch_hook(); " BLX R1 \n" // R0 is new process SP; " LDMIA R0!, {R4-R11, LR} \n" // Restore r4-11 and LR from new process stack " TST LR, #0x10 \n" // exc_return[4]=0? (it means that new process " IT EQ \n" // has active floating point context) " VLDMIAEQ R0!, {S16-S31} \n" // if so - restore it. " MSR PSP, R0 \n" // Load PSP with new process SP " CPSIE I \n" " BX LR \n" // Return to saved exc_return. Exception return will restore remaining context : : ); #endif // #if (defined __SOFTFP__) #endif // #if (defined __ARM_ARCH_6M__) } А это функция старта оси, также для среды IAR: extern "C" NORETURN void os_start(stack_item_t *sp) { // Set PendSV lowest priority value #if (defined SHP3_WORD_ACCESS) SHPR3 |= (0xFF << 16); #else PendSvPriority = 0xFF; #endif #if (!defined __SOFTFP__) FPCCR |= ASPEN | LSPEN; #endif asm volatile ( #if (defined __SOFTFP__) // code without FPU " LDR R4, [%[stack], #(4 * 14)] \n" // Load process entry point into R4 " ADDS %[stack], #(4 * 16) \n" // emulate context restore #else " LDR R4, [%[stack], #(4 * 15)] \n" // Load process entry point into R4 " ADD %[stack], #(4 * 17) \n" // emulate context restore #endif " MSR PSP, %[stack] \n" // store process SP to PSP " MOVS R0, #2 \n" // set up the current (thread) mode: use PSP as stack pointer, privileged level " MSR CONTROL, R0 \n" " ISB \n" // Insert a barrier : [stack]"+r" (sp) // output ); asm volatile ( " MOV R1, %0 \n" // Init and run system timer " BLX R1 \n" // " CPSIE I \n" // Enable interrupts at processor level " BX R4 \n" // Jump to process exec() function : :"r" (__init_system_timer) // output ); } В результате я перенёс некоторые функции, приведя в соответствие с версией для GCC и избавился от файла os_target_asm.s
  4. TEventFlag.Signal_isr()

    Это определение для файла "*.s", т.е. чисто ассемблерное.
  5. TEventFlag.Signal_isr()

    Только сегодня добрался до проекта. Работа, однако! Итак, дело действительно было в приоритетах и только в приоритетах. Я их поправил и всё заиграло! И вот что я сделал по-быстрому: 1. Назначил константы регистров и констант приоритетов: #if defined __ARM_ARCH_6M__ // Cortex-M0(+)/Cortex-M1 NVIC_SYSPRI14 EQU 0xE000ED20 // System priority register (priority 12..15). NVIC_PENDSV_PRI EQU 0x00C00000 // PendSV priority value (lowest) NVIC_SYSPRI15 EQU 0xE000ED20 // System priority register (priority 12..15). NVIC_ST_PRI EQU 0xC0000000 // SysTick priority value (lowest) #else NVIC_SYSPRI14 EQU 0xE000ED22 // System priority register (priority 14). NVIC_PENDSV_PRI EQU 0xFF // PendSV priority value (lowest). NVIC_SYSPRI15 EQU 0xE000ED23 // System priority register (priority 15). NVIC_ST_PRI EQU 0xFF // SysTick priority value (lowest). #endif NVIC_ST_CTRL EQU 0xE000E010 // SysTick Ctrl & Status Reg. NVIC_ST_RELOAD EQU 0xE000E014 // SysTick Reload Value Reg. NVIC_ST_CTRL_CLK_SRC EQU 0x00000004 // Clock Source. NVIC_ST_CTRL_INTEN EQU 0x00000002 // Interrupt enable. NVIC_ST_CTRL_ENABLE EQU 0x00000001 // Counter mode. 2. Поправил загрузку приоритета PendSV в os_start: os_start #if defined __ARM_ARCH_6M__ // Cortex-M0(+)/Cortex-M1 LDR R1, =NVIC_SYSPRI14 // Set the SysTick exception priority (lowest) LDR R2, =NVIC_PENDSV_PRI LDR R3, [R1] ADD R2, R3 STR R2, [R1] #else LDR R1, =NVIC_SYSPRI14 // Set the PendSV exception priority (lowest) LDR R2, =NVIC_PENDSV_PRI STRB R2, [R1] #endif 3. Поправил загрузку приоритета SysTick в init_system_timer: init_system_timer #if defined __ARM_ARCH_6M__ // Cortex-M0(+)/Cortex-M1 LDR R1, =NVIC_SYSPRI15 // Set the SysTick exception priority (lowest) LDR R2, =NVIC_ST_PRI LDR R3, [R1] ADD R2, R3 STR R2, [R1] #else LDR R1, =NVIC_SYSPRI15 // Set the SysTick exception priority (lowest) LDR R2, =NVIC_ST_PRI STRB R2, [R1] #endif Всем спасибо! PS Хотел сделать по-красивому, как для mx-gcc, но не пошла строчка: " LDR R1, =os_context_switch_hook \n" // call os_context_switch_hook(); Как сделать видимой для IAR-овского встроенного ассемблера адрес функции из другого модуля?
  6. TEventFlag.Signal_isr()

    Вот приоритеты: //----------------------------------------------------------------------------- // EQUATES // NVIC_SYSPRI14 EQU 0xE000ED22 // System priority register (priority 14). NVIC_PENDSV_PRI EQU 0xFF // PendSV priority value (lowest). NVIC_SYSPRI15 EQU 0xE000ED23 // System priority register (priority 15). NVIC_ST_PRI EQU 0xFF // SysTick priority value (lowest). NVIC_ST_CTRL EQU 0xE000E010 // SysTick Ctrl & Status Reg. NVIC_ST_RELOAD EQU 0xE000E014 // SysTick Reload Value Reg. NVIC_ST_CTRL_CLK_SRC EQU 0x00000004 // Clock Source. NVIC_ST_CTRL_INTEN EQU 0x00000002 // Interrupt enable. NVIC_ST_CTRL_ENABLE EQU 0x00000001 // Counter mode. Присваивание приоритетов: //----------------------------------------------------------------------------- // Perform systick timer initialization. // init_system_timer LDR R1, =NVIC_SYSPRI15 // Set the SysTick exception priority (lowest) LDR R2, =NVIC_ST_PRI STRB R2, [R1] LDR R1, =NVIC_ST_RELOAD // Setup SysTick LDR R2, =(SYSTICKFREQ/SYSTICKINTRATE-1) STR R2, [R1] LDR R1, =NVIC_ST_CTRL // Enable and run SysTick LDR R2, =(NVIC_ST_CTRL_CLK_SRC | NVIC_ST_CTRL_INTEN | NVIC_ST_CTRL_ENABLE) STR R2, [R1] BX LR //----------------------------------------------------------------------------- // START MULTITASKING // void os_start(stack_item_t* sp) // // Note(s) : 1) os_start() MUST: // a) Setup PendSVexception priority to lowest; // B) Setup system timer (exception priority and reload value); // c) Enable interrupts (tasks will run with interrupts enabled). // d) Jump to exec() function of the highest priority process. // os_start LDR R1, =NVIC_SYSPRI14 // Set the PendSV exception priority (lowest) LDR R2, =NVIC_PENDSV_PRI STRB R2, [R1] #ifdef __SOFTFP__ LDR R4, [R0, #(4 * 14)] // Load process entry point into R3 ADDS R0, R0, #(4 * 16) // emulate context restore #else LDR R4, [R0, #(4 * 15)] ADDS R0, R0, #(4 * 16) #endif MSR PSP, R0 // store process SP to PSP MOVS R0, #2 // Switch thread mode stack to PSP MSR CONTROL, R0 ISB // Insert a barrier #if USE_SYSTICK_TIMER != 0 LDR R1, =init_system_timer // Init and run system timer BLX R1 #endif CPSIE I // Enable interrupts at processor level BX R4 // Jump to process exec() function
  7. TEventFlag.Signal_isr()

    Простите, не понял сразу. PendSV_Handler #if defined __ARM_ARCH_6M__ // Cortex-M0(+)/Cortex-M1 CPSID I // Prevent interruption during context switch MRS R0, PSP // Load process stack pointer to R0 SUBS R0, R0, #32 // Adjust R0 to point to top of saved context in stack MOV R1, R0 // Preserve R0 (needed for os_context_switch_hook() call) STMIA R1!, {R4-R7} // Save low portion of remaining registers (r4-7) on process stack MOV R4, R8 // Move high portion of remaining registers (r8-11) to low registers MOV R5, R9 MOV R6, R10 MOV R7, R11 STMIA R1!, {R4-R7} // Save high portion of remaining registers (r8-11) on process stack // At this point, entire context of process has been saved PUSH {LR} // we must save LR (exc_return value) until exception return LDR R1, =os_context_switch_hook // call os_context_switch_hook(); BLX R1 // R0 is new process SP; ADDS R0, R0, #16 // Adjust R0 to point to high registers (r8-11) LDMIA R0!, {R4-R7} // Restore r8-11 from new process stack MOV R8, R4 // Move restored values to high registers (r8-11) MOV R9, R5 MOV R10, R6 MOV R11, R7 MSR PSP, R0 // R0 at this point is new process SP SUBS R0, R0, #32 // Adjust R0 to point to low registers LDMIA R0!, {R4-R7} // Restore r4-7 CPSIE I POP {PC} // Return to saved exc_return. Exception return will restore remaining context #else Если есть необходимость, могу загрузить проект. Но Вы под IAR-ом не работаете. Для визуального контроля границ стеков процессов добавил в функцию TBaseProcess::init_stack_frame возможность записи заголовков в формате "ProcXX". Хорошо видно тогда в дампе памяти дно стека. Если затёрт заголовок полностью - хана, стек закончился! А выглядит это так: или вот так: Код функции: //------------------------------------------------------------------------------ void TBaseProcess::init_stack_frame( stack_item_t * Stack , void (*exec)() #if scmRTOS_DEBUG_ENABLE == 1 , stack_item_t * StackBegin #endif ) { // ARM Architecture Procedure Call Standard [AAPCS] requires 8-byte stack alignment: StackPointer = (stack_item_t*)((uintptr_t)Stack & 0xFFFFFFF8); // Prepare Process Stack Frame. *(--StackPointer) = 0x01000000UL; // xPSR *(--StackPointer) = reinterpret_cast<uint32_t>(exec); // Entry Point StackPointer -= 14; // emulate "push R14,R12,R3,R2,R1,R0,R11-R4" #if scmRTOS_DEBUG_ENABLE == 1 for (stack_item_t* pDst = StackBegin; pDst < StackPointer; ++pDst) *pDst = STACK_DEFAULT_PATTERN; stack_item_t* pDst = StackBegin; *pDst++ = 0x636f7250; int a = this->priority()& 0x0000003F; if (a == prIDLE) { *pDst = 0x454c4449; return; } #if scmRTOS_PRIORITY_ORDER > 0 a = scmRTOS_PROCESS_COUNT - a; #endif int b = 48; while (a>10) { b++; a -= 10; } b += (a+48)<<8; *pDst = b; #endif // scmRTOS_DEBUG_ENABLE } Эту фичу можно включить с помощью макроса scmRTOS_DEBUG_ENABLE
  8. TEventFlag.Signal_isr()

    Да, не видно. То, что удалось словить, - это уже следствие. Ближе я пока что не подобрался. Поэтому и спрашиваю многоуважаемое сообщество, как можно заглянуть поглубже. Банальная точка останова на коде, который вызывается из множества мест, не поможет. Городить средства профилировки? Сложно и можно испортить что-то ещё, появятся артефакты, с которыми тоже придётся повоевать. Может, у кого есть уже опробованное средство, а?
  9. TEventFlag.Signal_isr()

    scmRTOS v5.1 IAR 7.70 Windows 10
  10. TEventFlag.Signal_isr()

    Это было сделано в первую очередь. Я не новичок в осях и понимаю подводность камней. Лет 10 назад починил PicOS18. Там при определённых условиях стек Idle восстанавливался не полностью, из-за чего происходило переполнение стеков. Тяжёлая ошибка.
  11. TEventFlag.Signal_isr()

    Весь день просидел и пытался подобраться поближе к источнику проблемы. Точно не обнаружил, но у меня складывается впечатление, что происходит то, что написано в руководстве о планировщике и о нарушении целостности системы. В связи с этим подскажите, как исследовать эту часть так, чтобы можно было в режиме реального времени обнаружить источник. Пошаговое прохождение не приводит к фатальному исходу. Можно ухитриться словить только хвост проблемы, да и то самый кончик. Я это выложил в виде скриншотов. Когда-то код, связанный с перепланировкой, наверняка подвергался отладке, иначе в руководстве не уделяли подробному описанию проблемы, которая очень похожа на эту. Либо как вариант использовать планировщик с прямой передачей управления.
  12. TEventFlag.Signal_isr()

    Словил за хвост эту проблему. Словами или кодом описывать тяжеловато, поэтому сделал скриншоты практически пошагового прохождения. Из-за большого объёма топика всё спрятал в прикреплённом файле. Doc1.zip
  13. TEventFlag.Signal_isr()

    Ща попробую Контекст портится после suspend(ProcessMap); Я поставил точку останова на if(is_timeouted(ProcessMap)), а там уже запорчено. Я так понимаю: suspend останавливает процесс, а потом перепланировщик его возобновляет. И при восстановлении контекста что-то происходит.
  14. TEventFlag.Signal_isr()

    Доброго дня! Решил поднять тему вот таким вопросом. Создаю ПО под Freescale M0+ с использованием scmRTOS. Четыре процесса: typedef OS::process<OS::pr0, 512> TProc1; typedef OS::process<OS::pr1, 512> TProc2; typedef OS::process<OS::pr2, 512> I2C0_TASK; typedef OS::process<OS::pr3, 1024> TBackgroundProc; Есть прерывания: TRTC rtc; OS_INTERRUPT void RTC_second_Handler() { OS::TISRW TISRW_O; rtc.RtcSecondIrqHandler(); OneSecondFlag.signal_isr(); } Устанавливаю флаг в прерывании и ловлю его в процессе TProc1: template<> OS_PROCESS void TProc1::exec() { for(;;) { OneSecondFlag.wait(); // while (!rtc.getNewSecondFlag()); led_bl.Cpl(); sleep(5); } } Вылетает по HardFault. Если закомментировать OneSecondFlag.signal_isr(); то не вылетает. Ковыряюсь уже довольно долго. Накопал, что при восстановлении контекстов из критических секций происходит лишнее действие, которое затирает правильно восстановленный контекст. Если использовать флаг rtc.getNewSecondFlag(), вызываемый из объекта, то всё ОК. Куда копать? Вдогонку: Вылетает при выполнении кода: bool OS::TEventFlag::wait(timeout_t timeout) { TCritSect cs; if(Value) // if flag already signaled { Value = efOff; // clear flag return true; } else { cur_proc_timeout() = timeout; suspend(ProcessMap); if(is_timeouted(ProcessMap)) return false; // waked up by timeout or by externals cur_proc_timeout() = 0; <== вылетает при попытке выполнить эту инструкцию - обращение к несуществующей памяти return true; // otherwise waked up by signal() or signal_isr() } }
  15. Спасибо, ребята! Особенно про идею владельца. Я об этом как-то не подумал. Считал, что драйвер сам по себе. Я как-то лет 7 назад поднимал PICos18. Там драйверы были оформлены как самостоятельные задачи с FIFO. Кидаешь туда из разных задач с признаком, какая задача это сделала, и возвращалось всегда по этому признаку. Согласен AHTOXA, протокол навороченный. Так зато ноги только две! 1-wire ещё навороченнее! У меня выбора нет, пилю I2C stm-овский. Результаты буду выкладывать.
  16. Спасибо! Не хотел обидеть. AHTOXA сделал софтовый I2C драйвер. А мне нужен для штатной периферии. Вот, набросал по образу и подобию SPI драйвера из stm32_spi.h. stm32_i2c_L4xx.zip
  17. Есть. Но это следующий шаг. И пинать меня ногами не следует за то, что спросил. Я хочу научиться использовать библиотеку, а не упражняться в словесности. Поэтому и обратился за помощью. Простите за оффтоп.
  18. примеры под stm32tpl

    Доброго дня всем! Понравилась мне библиотека stm32tpl от AHTOXA, да вот что-то не хватает умения применить её. А для завязки подкину задачку. Есть на шине I2C память и ЖК-индикатор. Драйвер I2C должен быть общим. А его должны юзать драйверы устройств: lcd и mem. Подскажите, как это сделать в scmRTOS из разных задач. Спасибо!
  19. Вся оптимизация выключена, что в компиляторе, что в линкере А когда выставил High, Balanced, собралось. И даже заработало!
  20. Суть проблемы. В проекте подключил библиотеку stm32tpl (крайняя версия) и объявил согласно инструкции: в main.cpp: typedef Pin<'E', 1, 'H', PIN_SPEED_VERY_LOW> PIN_BL; ... void main() { RCC->AHB2ENR |= RCC_AHB2ENR_GPIOEEN; // AHB1, 50 MHz PIN_BL::Mode(OUTPUT); OS::run(); } линкер ругается: Error[Li005]: no definition for "Pin<(char)69, (int)1, (char)72, (PinSpeed)0>::GPIOx" [referenced from D:\prj\scm_3\iar\Debug\Obj\main.o] Методом возгонки и последующей абсорбции выделил следующее: в шаблоне структуры не создаётся указатель на GPIOx, который используется в дальнейшем функциями структуры. template<char port, int pin_no, char activestate, PinSpeed speed> struct Pin { static const uint32_t pin = pin_no; static const uint32_t port_no = port-'A'; static const uint32_t shift = pin; static const uint32_t shift_x2 = pin * 2; static const uint32_t shift_x4 = (pin % 8) * 4; static const uint32_t mask = 1UL << shift; static const uint32_t mask_x2 = 3UL << shift_x2; static const uint32_t mask_x4 = 0xFUL << shift_x4; static const uint32_t clearmask = 1UL << (pin + 16); enum { GPIOx_BASE = port_gpio_t<port>::GPIOx_BASE }; static struct { GPIOxTypeDef* operator-> () { return (GPIOxTypeDef*)GPIOx_BASE; } }GPIOx; ... INLINE static void SetMode(PinMode mode) { GPIOx->MODER = (GPIOx->MODER & ~mask_x2) | (mode << shift_x2); // Линкер выдаёт ошибку // ((GPIOxTypeDef*)GPIOx_BASE) -> MODER = (((GPIOxTypeDef*)GPIOx_BASE) -> MODER & ~mask_x2) | (mode << shift_x2); // Линкер НЕ выдаёт ошибку } Если использовать закомментированный код, то линкер не ругается. Подскажите, куда копать?
  21. SPIRIT1

    Spirit1 - это торговое название CC1101. Четыре года назад мы планировали работать на них, но обнаружилось, что его передатчик не проходит по стандарту EN300220. наш главный даже ездил в Осло по этому вопросу. Когда тамошним инженерам показали в чем дел и почему, то менеджеры стали грустные. А год назад нам принесли Spirit1. Потом мы узнали, что тексас продал этот голимый кристалл ST. Так что можете смело юзать инфу под СС1101. Проверено, подходит
  22. Отсутствие преамбулы значительно ухудшает качество приема трансиверами с автоматами-модемами. даже если перевести в режим raw. Проверено. наилучший выигрыш дают простые приемники, например, серии SYN, клонирующие Micrel. Они иногда даже исправляют микреловские ошибки. И полная обработка контроллером. На скорости 8000 с ООК получали -119дБ инструментальную чувствительность. И это без преамбулы! Причем анализировался код сразу трех протоколов, несовместимых между собой.
  23. Я не знаю, как правильно, но я делаю так. Повторяю референс дизайн, исследую, добиваюсь заявленных характеристик, а уж затем начинаю "издеваться". Всё дело в том, что референс дизайнс является той опорной точкой в исследованиях, которые неизбежно появятся в будущем. И как, простите, понять что-то в работе прибора, если сравнивать не с чем?
  24. Ad14

    Классная шутка: положить в закрома в папку 14.3.12 содержимое 14.3.11 :tongue: Sorry! Сам накосячил - из 11 папки залил. Определенно пора в отпуск! :bb-offtopic:
  25. Сабунина тоже лишить премии :) - в его видеоуроке показана именно P-CADовская настройка цветов.
×
×
  • Создать...