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

maxntf

Участник
  • Постов

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

  • Посещение

Сообщения, опубликованные maxntf


  1. On 10/27/2018 at 11:45 AM, ViKo said:

    Покажу мой обработчик. :)

    
    /*!*****************************************************************************
      @brief	Simple HardFault Handler
      @details	В пошаговом режиме переставить программный счетчик на BX и шагнуть
      @note		PC будет содержать команду, следующую за вызвавшей сбой
      */
    __asm void HardFault_Handler(void)
    {
    	B .
    	BX LR
    }

     

    У меня при таких действиях происходит следующее:
    Первый брекпоинт на 'B .' PC = текущему адресу, LR = 0xFFFFFFF1
    Переставляю указатель на BX LR, делаю шаг в отладчике и получаю
    PC = 0х000010BC, LR = 0x00000F03.
    Это вообще похоже на системную память. Что я делаю не так?

  2. Вот полный пример кода исследования HatdFault.

    HardFaultHandler.s

    AREA OSKERNEL, CODE, READONLY, ALIGN=2
     PRESERVE8
     EXPORT HardFault_Handler
     IMPORT HardFaultHandler_c
     THUMB
    
    HardFault_Handler
     movs R0, #4
     mov R1, LR
     tst R0, R1 ;// Check EXC_RETURN in Link register bit 2.
     bne Uses_PSP
     mrs R0, MSP ;// Stacking was using MSP.
     b Pass_StackPtr
    
    Uses_PSP
     mrs R0, PSP ;// Stacking was using PSP.
    
    Pass_StackPtr
     ALIGN
     ldr R2,=HardFaultHandler_c
     bx R2 ;// Stack pointer passed through R0.
    
    END

    HardFaultHandler_c.c

    // System Handler Control and State Register
    #define SYSHND_CTRL (*(volatile unsigned int*) (0xE000ED24u))
    // Memory Management Fault Status Register
    #define NVIC_MFSR (*(volatile unsigned char*) (0xE000ED28u))
    // Bus Fault Status Register
    #define NVIC_BFSR (*(volatile unsigned char*) (0xE000ED29u))
    // Usage Fault Status Register
    #define NVIC_UFSR (*(volatile unsigned short*)(0xE000ED2Au))
    // Hard Fault Status Register
    #define NVIC_HFSR (*(volatile unsigned int*) (0xE000ED2Cu))
    // Debug Fault Status Register
    #define NVIC_DFSR (*(volatile unsigned int*) (0xE000ED30u))
    // Bus Fault Manage Address Register
    #define NVIC_BFAR (*(volatile unsigned int*) (0xE000ED38u))
    // Auxiliary Fault Status Register
    #define NVIC_AFSR (*(volatile unsigned int*) (0xE000ED3Cu))
    
    static volatile unsigned int _Continue; // Set this variable to 1 to run further
    static struct {
     struct {
     volatile unsigned int r0; // Register R0
     volatile unsigned int r1; // Register R1
     volatile unsigned int r2; // Register R2
     volatile unsigned int r3; // Register R3
     volatile unsigned int r12; // Register R12
     volatile unsigned int lr; // Link register
     volatile unsigned int pc; // Program counter
     union {
     volatile unsigned int byte;
     struct {
     unsigned int IPSR : 8; // Interrupt Program Status register (IPSR)
     unsigned int EPSR : 19; // Execution Program Status register (EPSR)
     unsigned int APSR : 5; // Application Program Status register (APSR)
     } bits;
     } psr; // Program status register.
     } SavedRegs;
     union {
     volatile unsigned int byte;
     struct {
     unsigned int MEMFAULTACT : 1; // Read as 1 if memory management fault
     // is active
     unsigned int BUSFAULTACT : 1; // Read as 1 if bus fault exception is active
     unsigned int UnusedBits1 : 1;
     unsigned int USGFAULTACT : 1; // Read as 1 if usage fault exception
     // is active
     unsigned int UnusedBits2 : 3;
     unsigned int SVCALLACT : 1; // Read as 1 if SVC exception is active
     unsigned int MONITORACT : 1; // Read as 1 if debug monitor exception
     // is active
     unsigned int UnusedBits3 : 1;
     unsigned int PENDSVACT : 1; // Read as 1 if PendSV exception is active
     unsigned int SYSTICKACT : 1; // Read as 1 if SYSTICK exception is active
     unsigned int USGFAULTPENDED : 1; // Usage fault pended; usage fault started
     // but was replaced by a higher-priority
     // exception
     unsigned int MEMFAULTPENDED : 1; // Memory management fault pended; memory
     // management fault started but was
     // replaced by a higher-priority exception
     unsigned int BUSFAULTPENDED : 1; // Bus fault pended; bus fault handler was
     // started but was replaced by a
     // higher-priority exception
     unsigned int SVCALLPENDED : 1; // SVC pended; SVC was started but was
     // replaced by a higher-priority exception
     unsigned int MEMFAULTENA : 1; // Memory management fault handler enable
     unsigned int BUSFAULTENA : 1; // Bus fault handler enable
     unsigned int USGFAULTENA : 1; // Usage fault handler enable
     } bits;
     } syshndctrl; // System Handler Control and State
     // Register (0xE000ED24)
     union {
     volatile unsigned char byte;
     struct {
     unsigned char IACCVIOL : 1; // Instruction access violation
     unsigned char DACCVIOL : 1; // Data access violation
     unsigned char UnusedBits : 1;
     unsigned char MUNSTKERR : 1; // Unstacking error
     unsigned char MSTKERR : 1; // Stacking error
     unsigned char UnusedBits2 : 2;
     unsigned char MMARVALID : 1; // Indicates the MMAR is valid
     } bits;
     } mfsr; // Memory Management Fault Status
     // Register (0xE000ED28)
     union {
     volatile unsigned int byte;
     struct {
     unsigned int IBUSERR : 1; // Instruction access violation
     unsigned int PRECISERR : 1; // Precise data access violation
     unsigned int IMPREISERR : 1; // Imprecise data access violation
     unsigned int UNSTKERR : 1; // Unstacking error
     unsigned int STKERR : 1; // Stacking error
     unsigned int UnusedBits : 2;
     unsigned int BFARVALID : 1; // Indicates BFAR is valid
     } bits;
     } bfsr; // Bus Fault Status Register (0xE000ED29)
     volatile unsigned int bfar; // Bus Fault Manage Address Register
     // (0xE000ED38)
     union {
     volatile unsigned short byte;
     struct {
     unsigned short UNDEFINSTR : 1; // Attempts to execute an undefined
     // instruction
     unsigned short INVSTATE : 1; // Attempts to switch to an invalid state
     // (e.g., ARM)
     unsigned short INVPC : 1; // Attempts to do an exception with a bad
     // value in the EXC_RETURN number
     unsigned short NOCP : 1; // Attempts to execute a coprocessor
     // instruction
     unsigned short UnusedBits : 4;
     unsigned short UNALIGNED : 1; // Indicates that an unaligned access fault
     // has taken place
     unsigned short DIVBYZERO : 1; // Indicates a divide by zero has taken
     // place (can be set only if DIV_0_TRP
     // is set)
     } bits;
     } ufsr; // Usage Fault Status Register (0xE000ED2A)
     union {
     volatile unsigned int byte;
     struct {
     unsigned int UnusedBits : 1;
     unsigned int VECTBL : 1; // Indicates hard fault is caused by failed
     // vector fetch
     unsigned int UnusedBits2 : 28;
     unsigned int FORCED : 1; // Indicates hard fault is taken because of
     // bus fault/memory management fault/usage
     // fault
     unsigned int DEBUGEVT : 1; // Indicates hard fault is triggered by
     // debug event
     } bits;
     } hfsr; // Hard Fault Status Register (0xE000ED2C)
     union {
     volatile unsigned int byte;
     struct {
     unsigned int HALTED : 1; // Halt requested in NVIC
     unsigned int BKPT : 1; // BKPT instruction executed
     unsigned int DWTTRAP : 1; // DWT match occurred
     unsigned int VCATCH : 1; // Vector fetch occurred
     unsigned int EXTERNAL : 1; // EDBGRQ signal asserted
     } bits;
     } dfsr; // Debug Fault Status Register (0xE000ED30)
     volatile unsigned int afsr; // Auxiliary Fault Status Register
     // (0xE000ED3C) Vendor controlled (optional)
    } HardFaultRegs;
    
    void HardFaultHandler_c(unsigned int* pStack);
    void HardFaultHandler_c(unsigned int* pStack) {
    
    if (NVIC_HFSR & (1uL << 31)) {
     NVIC_HFSR |= (1uL << 31); // Reset Hard Fault status
     *(pStack + 6u) += 2u; // PC is located on stack at SP + 24 bytes;
     // increment PC by 2 to skip break instruction.
     return; // Return to interrupted application
    }
     //
     // Read NVIC registers
     //
     HardFaultRegs.syshndctrl.byte = SYSHND_CTRL; // System Handler Control and
     // State Register
     HardFaultRegs.mfsr.byte = NVIC_MFSR; // Memory Fault Status Register
     HardFaultRegs.bfsr.byte = NVIC_BFSR; // Bus Fault Status Register
     HardFaultRegs.bfar = NVIC_BFAR; // Bus Fault Manage Address Register
     HardFaultRegs.ufsr.byte = NVIC_UFSR; // Usage Fault Status Register
     HardFaultRegs.hfsr.byte = NVIC_HFSR; // Hard Fault Status Register
     HardFaultRegs.dfsr.byte = NVIC_DFSR; // Debug Fault Status Register
     HardFaultRegs.afsr = NVIC_AFSR; // Auxiliary Fault Status Register
     //
     // Halt execution
     // If NVIC registers indicate readable memory, change the variable value
     // to != 0 to continue execution.
     //
     _Continue = 0u;
     while (_Continue == 0u);
     //
     // Read saved registers from the stack
     //
     HardFaultRegs.SavedRegs.r0 = pStack[0]; // Register R0
     HardFaultRegs.SavedRegs.r1 = pStack[1]; // Register R1
     HardFaultRegs.SavedRegs.r2 = pStack[2]; // Register R2
     HardFaultRegs.SavedRegs.r3 = pStack[3]; // Register R3
     HardFaultRegs.SavedRegs.r12 = pStack[4]; // Register R12
     HardFaultRegs.SavedRegs.lr = pStack[5]; // Link register LR
     HardFaultRegs.SavedRegs.pc = pStack[6]; // Program counter PC
     HardFaultRegs.SavedRegs.psr.byte = pStack[7]; // Program status word PSR
     //
     // Halt execution
     // To step out of the HardFaultHandler, change the variable value to != 0.
     //
     _Continue = 0u;
     while (_Continue == 0u) {
     }
    }

    В общем после вылета в HardFault в режиме отладки проверяю структуру HardFaultRegs и там все значения 0. Где то ошибка в функции, как узнать причину?

  3. Прошу прощения, только создал сообщение и нашел ошибку. 

    IMPORT HardFault_Handler

    Брал из готового примера. Неудобно когда похожие названия.

    В общем исправил, вроде все собралось, буду проверять.

    EXPORT HardFault_Handler
    
    IMPORT HardFaultHandler_с
    
    ...
    
    ldr R2,=HardFaultHandler_с
    
    И в main.c
    
    extern void HardFaultHandler_с(unsigned int* pStack);
    void HardFaultHandler_с(unsigned int* pStack){
    	
    }

     

  4. Хочу включить в проект на Keil исследование причины вылета в HardFault. Но в ассемблере никак не могу разобраться. Смысл я в общем понял в ассемблерном куске кода копируются данные регистров которые нужно проверить, а в Си функции уже их разбираемым.

    Есть startupxxx.s файл, в нем есть описание этой функции по умолчанию и там стоит атрибут WEAK. Посмотрел он указывает на то, что эта функция может быть переопределена в другом месте и будет иметь приоритет. 

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

    Подскажите как правильно прикрутить asm файл с функцией HardFault, чтоб в main.c описать функцию void HardFaultHandler(unsigned int* pStack){...}

    ;----------------------------------------------------------------------
    ;File : HardFaultHandler.S
    ;Purpose : HardFault exception handler for Keil assembler.
    ;-------- END-OF-HEADER ---------------------------------------------
    ;*/
    
     AREA OSKERNEL, CODE, READONLY, ALIGN=2
     PRESERVE8
     EXPORT HardFault_Handler
    
     IMPORT HardFault_Handler
    
     THUMB
    
    
    HardFault_Handler
    
     ;// This version is for Cortex M0
     movs R0, #4
     mov R1, LR
     tst R0, R1 ;// Check EXC_RETURN in Link register bit 2.
     bne Uses_PSP
     mrs R0, MSP ;// Stacking was using MSP.
     b Pass_StackPtr
    
    Uses_PSP
    
     mrs R0, PSP ;// Stacking was using PSP.
    
    Pass_StackPtr
    
     ALIGN
    
     ldr R2,=HardFaultHandler
     bx R2 ;// Stack pointer passed through R0.
    
    
     END
    
    ;/****** End Of File *************************************************/

     

    Или второй вариант. Пробую написать этот код в startup файле

    ; Dummy Exception Handlers (infinite loops which can be modified)
    
    NMI_Handler     PROC
                    EXPORT  NMI_Handler                    [WEAK]
                    B       .
                    ENDP
    HardFault_Handler\
                    PROC
                    EXPORT  HardFault_Handler              [WEAK]
    ;// This version is for Cortex M0
     movs R0, #4
     mov R1, LR
     tst R0, R1 ;// Check EXC_RETURN in Link register bit 2.
     bne Uses_PSP
     mrs R0, MSP ;// Stacking was using MSP.
     b Pass_StackPtr
    
    Uses_PSP
    
     mrs R0, PSP ;// Stacking was using PSP.
    
    Pass_StackPtr
    
     ALIGN
    
     ldr R2,=HardFaultHandler
     bx R2 ;// Stack pointer passed through R0.
    					
                    B       .
                    ENDP
    SVC_Handler     PROC
    ...

    А в main.c прописываю

    extern void HardFaultHandler(unsigned int* pStack);
    void HardFaultHandler(unsigned int* pStack){
    ...	
    }

    Тогда компилятор ругается что в startup файле символ HardFaultHandler не определен. Может его нужно как то определить в startup.s а не в main.c

  5. Кстати, вот что-то интересное пишут.

    Спасибо! То, что нужно.

    FUNC void Setup (void) {
    
    SP = _RDWORD(0x08005000); // Setup Stack Pointer
    PC = _RDWORD(0x08005004); // Setup Program Counter
    XPSR = 0x01000000; // Set Thumb bit
    
    }
    
    Setup();
    LOAD %L INCREMENTAL nocode // load debug info without performing reset
    
    FUNC void OnResetExec(void) {
        Setup();
    }

  6. SP=*(int*)0x08000000

    PC=*(int*)0x08000004

     

    Это куда?

    Вот файлик debug.ini

    FUNC void Setup (void) {
    
    SP = _RDWORD(0x08005000); // Setup Stack Pointer
    PC = _RDWORD(0x08005004); // Setup Program Counter
    XPSR = 0x01000000; // Set Thumb bit
    
    }
    
    Setup();
    LOAD %L INCREMENTAL nocode // load debug info without performing reset

     

    Там бы дописать что-то типа:

    IF(RESET) Setup();

     

    Только возможно ли такое?

    У меня сейчас получается что при загрузке отладчика срабатывает функция Setup(), а когда я нажимаю в нем Reset то SP и PC сбрасываются. И получается что нужно перезагружать отладчик.

  7. Отлаживаю в Keil - ST-Link Debugger.

     

    Попробовал по совету x893 создал файл debug.ini. Похоже это то, что мне нужно. Только там получается что при запуске отладчика, он стартует с 0x08005004, а после reset(в отладчике) уже с 0x08000004.

    Помогите пожалуйста допилить этот ini.

  8. Подскажите как отладчику указать, чтоб он стартовал с определенного адреса?

    Читал, что вроде как нужно в скаттер файле определить точку входа через команду ENTRY. Только как это сделать я не знаю, что указывать в ее параметрах?

    Или это не то?

    Сам файл у меня тот, что предлагается стандартно (с измененной адресацией под бут)

    ; *************************************************************
    ; *** Scatter-Loading Description File generated by uVision ***
    ; *************************************************************
    
    LR_IROM1 0x08005000 0x0000B000  {   ; load region size_region
      ER_IROM1 0x08005000 0x0000B000  { ; load address = execution address
       *.o (RESET, +First)
       *(InRoot$$Sections)
       .ANY (+RO)
      }
      RW_IRAM1 0x200000C0 0x00001F40  { ; RW data
       .ANY (+RW +ZI)
      }
    }

  9. Сейчас принято делать так: http://www.keil.com/support/man/docs/armcc...59124981436.htm

    Спасибо, понял в чем тут дело.

    Просто раньше работал только с 8 битными МК, там таких проблем нет.

     

    А у меня получилось, что буфер char - выравнивание у него по одному байту (без атрибута, начинаться может с любого адреса), а в качестве аргумента функции я передаю указатель на этот буфер с приведением типа до uint32.

  10. Всем привет, наткнулся на такой баг - объявил буфер в глобальных переменных.

    Передаю его адрес в аргументе функции. И когда обращаюсь в функции к этой переменной через указатель сразу вылетаю в HardFault_Handler.

    Пол дня парился, и в конце концов выяснил, что линковщик расположил ее по адресу не кратному 4.

    Проверил, действительно если передать в функцию указатель не кратный 4, то при чтении по этому адресу вылетаем в HardFault_Handler.

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

    Что делать?

    img.jpg

     

    P.S

    Keil V5.23.0.0

     

     

  11. Народ подскажите, натолкнулся на такую штуку:

    Включен USART1 на прием и разрешен только один тип прерывания по приему байта.

    void USART1_IRQHandler(void){
        char bt;
        if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET){
            bt = (char)USART_ReceiveData(USART1);
            USART_ClearITPendingBit(USART1, USART_IT_RXNE);
            if(bt != 0){
            bUartRx[cUartRx] = bt;
            if(cUartRx >= (BRXSIZE-2)) bUartRx[(BRXSIZE-1)] = 0, cUartRx = 0, fUartRxOver = 1;
                else cUartRx++, bUartRx[cUartRx] = 0;
            xSemaphoreGiveFromISR(xSemRxInBuf, NULL);
            }
        }                                                            
    }
    
    void UART_Init(void){
        GPIO_InitTypeDef GPIO_InitStruct;
        USART_InitTypeDef USART_InitStruct;
        NVIC_InitTypeDef NVIC_InitStruct;
        
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
        
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;    
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
            GPIO_Init(GPIOA, &GPIO_InitStruct);
        GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
            GPIO_Init(GPIOA, &GPIO_InitStruct);
            GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
            GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
        
        USART_InitStruct.USART_BaudRate = 19200;
        USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_InitStruct.USART_Parity = USART_Parity_No;
        USART_InitStruct.USART_StopBits = USART_StopBits_1;
        USART_InitStruct.USART_WordLength = USART_WordLength_8b;
            USART_Init(USART1, &USART_InitStruct);
            USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
            USART_Cmd(USART1, ENABLE);
    
        NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
        NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
        NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
            NVIC_Init(&NVIC_InitStruct);

     

    Так вот, во время отладки при нажатии Stop или остановки по брекпоинту, если в этот момент что то принималось в UART, то после запуска отладчика все время висим в обработчике прерывания. Причем все флаги сброшены и больше не устанавливаются, даже если приходят данные.

     

    P.S.

    STM32F051R8T6

    Keil v.5.23.0.0

  12. Всем привет.

    Для написания собственного бутлоадера, интересует что находится между окончанием таблицы прерываний и адресом входа в основную программу (в частности начало файла startup)?

    Начинается с такого:

    0x080000C0 F000F802  BL.W     __scatterload (0x080000C8)
    0x080000C4 F000F83E  BL.W     __rt_entry (0x08000144)
    0x080000C8 A00C      ADR      r0,{pc}+0x34; @0x080000FC
    ...

    Это в Keil по крайне мере.

    В отладчике проверил, в этот кусок кода попадаем в конце выполнения startup файла.

    Мысль одна, что это какая то подготовка регистров ядра. Кто может подсказать, там есть что-то важное или на этот кусок не нужно обращать внимания (не трогать его вообще) и там все всегда стандартно (одинаково)? Если этот код будет дублироваться как в самом загрузчике, так и в основной программе - это нормально?

    Или может в проекте с основной программой нужно как то написать scatter файл, чтоб проект вообще компилировался без этой инициализации и startup файла?

  13. Компаратор там внутри приемника ...

    Так в этих походу тоже. Я ведь не 433МГц принимаю, а то что выдает компаратор данного приемника. И задача практически аналогична, там преамбула и блок данных.

    Только тот компаратор что в приемнике не всегда выдает нормальный сигнал (когда помехи). Когда помех нет, сигнал как на первой картинки, а когда помехи как на второй. Но в том сигнале есть вся полезная часть, вот я и хочу ее выбирать (взять максимум с этого приемника).

    А по поводу NRF24L01. Нужно принимать сигнал с готовых устройств, работающих на частоте 433 и передающих данные в формате KeeLoq.

    P.S.

    Собственно задача попробовать сделать выборку по напряжению от 2,8В до 3,3В, а остальное откинуть.

  14. 1. Что за передатчик ?

    2. Что за линия связи ?

    3. А расстояние от передатчика до приемника какое ?

    4. Усилить сигнал передатчика никак не получится ?

    5. Странная картинка. Может, все-таки проще усилить сигнал ?

    Это радиоприемник H5V4D на частоте 433МГц.

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

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

    Сейчас принимаю сигнал с внешнего GPIO через EXTI прерывания. Сам не так давно работаю с STM. Сейчас посмотрел что там EXTI прерывание вроде как на выход компаратора можно настроить. Если так, то по идеи можно отследить нарастание и спад сигнала где-то в пределах от 2,8V до VDD там где полезная часть.

    Что скажете, или затея глупая?

  15. На выходе приемника при слабом уровне сигнала от передатчика получаем очень искаженный сигнал.

    Но по верхнему уровню сигнала вроде как видна полезная часть сигнала амплитудой примерно 0,5В.

    Приемник подключен к STM32F072. Какими аппаратными средствами можно отфильтровать такой сигнал?

    У меня пока напрашивается только вариант с АЦП.

    Длительность самого короткого импульса 280 мкс. Максимальная частота дескритизации АЦП на 12бит = 1Мгц. более чем достаточно.

    Опыта обработки сигналов мало, у кого есть дельные советы? Может еще нужно какой то фильтр поставить на входе МК.

    SDS00002.jpg

    SDS00001.jpg

     

  16. ...но со временем понял, что это более, чем правильное поведение отладчика...

    Не имею ни капли сомнения, что оно и правильно, и даже уже понимаю зачем. Со всей уверенностью считаю, что ребята которые все это разрабатывали по умнее всех нас вместе взятых. Хотел написать, что о такой фиче, нужно упоминать через каждую страницу мануала. А потом призадумался, может это такой тактический ход, для тех кто не особо любитель почитать? (пишу о себе:)). Пока это все разгребал, докапался до таких вещей, что неизвестно когда бы ещё специально лез в эти дебри.

    Но... Было бы чудесно, если бы отладчик спросил, делать переход по вектору прерывания или нет. Это очень удобно для освоения, когда начинающий ещё не знает куда должна пойти программа, и хочет по шагать.

  17. На всякий случай посмотрите, останавливается ли счет таймера (TIM10 вроде) в режиме отладки? Есть битик для этой цели.

    Из-за этого возможно, пока идете по шагам, заново входите в прерывание таймер, не успев попасть PendSV.

     

    Я даже уже перед выполнением:

    xSemaphoreGiveFromISR(xSem1ms, &xHigherPriorityTaskWoken);
    portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);

    Отключаю прерывания TIM10

     

    Вот весь проект, убрал все лишнее и переименовал задачи, номер задачи соответствует приоритету, а то я и сам уже начал путаться.

    xSemaphoreHandle xSem1ms;
    void Task1(void *pParams);
    void Task2(void *pParams);
    
    void TIM10_IRQHandler(void)
    {
    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;	
    if(TIM_GetFlagStatus(TIM10, TIM_FLAG_Update) != RESET)
    {
    		NVIC->ICER[TIM10_IRQn >> 0x05] = (uint32_t)0x01 << (TIM10_IRQn & (uint8_t)0x1F);
    		xSemaphoreGiveFromISR(xSem1ms, &xHigherPriorityTaskWoken);
    		portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
    }
    }
    int main(void)
    {	
    NVIC_InitTypeDef NVIC_InitStruct;
    
    RCC_HSICmd(ENABLE);
    while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
    RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
    RCC_HSEConfig(RCC_HSE_OFF);
     while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET);
    
    SystemCoreClockUpdate();
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    NVIC_InitStruct.NVIC_IRQChannel = TIM10_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 14;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    	NVIC_Init(&NVIC_InitStruct);
    
    xTaskCreate(Task1, "Task1-handler", configMINIMAL_STACK_SIZE, NULL, 1, NULL);	
    vTaskStartScheduler();
    
    }
    void Task1(void *pParams)
    {
    xTaskCreate(Task2, "Task2-handler", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
    while(1);
    }
    void Task2(void *pParams)
    {
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    
    vSemaphoreCreateBinary(xSem1ms);
    xSemaphoreTake(xSem1ms, 0);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10, ENABLE);
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period = 16000 - 1;
    TIM_TimeBaseInitStruct.TIM_Prescaler = 0;
    	TIM_TimeBaseInit(TIM10, &TIM_TimeBaseInitStruct);
    	TIM_ClearFlag(TIM10, TIM_FLAG_Update);
    	TIM_ITConfig(TIM10, TIM_IT_Update, ENABLE);
    	TIM_Cmd(TIM10, ENABLE);
    
    xSemaphoreTake(xSem1ms, 100);	
    vTaskDelete(NULL);
    }
    

     

    И на всякий случай заново опишу ситуацию.

    Со строчки portEND_SWITCHING_ISR(xHigherPriorityTaskWoken) если шагами, попадаем в Task1 - цикл while(1);

    А если через Run, то попадаем в Task2 на строку vTaskDelete(NULL);

     

    P.S.

    И напоследок. Проверил свое убеждение, что командами Step отладчик не попадает в прерывание, а Run попадает. Проверил на том же TIM10. Включил его, сразу установил флаг прерывания - если пройти его шагами, программа дальше пойдет не попадая в прерывания. А если через Run, то в прерывания попадает.

     

    Возможно 9 листов "ереси" того стоило? :)

    Уверен что не каждый, тем более начинающий об этом знает. И шагая по программе нужно учитывать что в это время могло произойти прерывание и жизнь пошла бы по другому.

  18. И наконец поставил четвертый брекпоинт в xPortPendSVHandler.

    Нахожусь на строчке portEND_SWITCHING_ISR(xHigherPriorityTaskWoken).

    2 раза нажимаю Step, попадаю в Task1.

    А нажимаю Run, попадаю вначале в xPortPendSVHandler, снова Run и на Task2 на строку после xSemaphoreTake

  19. Вангую, что переключение задачи на активную происходит лишь при отработке прерывания системного таймера.

    Нет.

    Поставил 3 брекпоинта. Task1, Task2 и в xPortSysTickHandler.

    Сразу попадаем в Task1.

     

    P.S.

    Возможно я ошибаюсь, но что то мне подсказывает, что по функции Step и Step Over отладчик не может попасть в прерывание, а собственно это и должно произойти после выход из обработчика прерывания TIM10, программа должна попасть в PendSV Handler.

  20. Оптимизацию отключите, хотя бы для debug сборки. При пошаговой отладке она только вредит.

    Или как вариант - ходить не по C/C++ исходникам, а в по командам в окне disasm.

    Оптимизация стоит Level 0, и сделал я это сразу после установки кейла. Никогда оптимизацию не использую.

    Да хоть по Cи, хоть по disasm. Был бы disbasic :) думаю так же работал.

     

    Эта реплика к чему?

    И вообще, изучайте инструмент, а то вон 8 страниц наплодили по сути на пустом месте :)

    Где про это сказано?

  21. Что же за отладчик такой, если не секрет?

    Тот что в Keil.

    Причем только в пошаговом режиме кнопками Step или Step Over при выходе из обработчика прерываний.

    А если поставить брекпоинты в задачах, и выйти из прерывания Step Out или Run тогда попадаем куда нужно, то есть в Task2.

×
×
  • Создать...