2024-12-29 06:52 AM
Hello, There
I am trying to implement NEC protocol to implement the IR remote driver, but my code is triggering the p infinte-loop. As I tried to find the problem. I think the problem caused by the following lines:
time = ((float)tim_Counter * time_interval / ARR); // caluclate time in ms
// start bit
if((time > 11 && time < 14) && recevied_data.startDected == 0) // start bit
recevied_data.startDected = 1;
// one is detected
else if((time > 2.0 && time < 2.5) && recevied_data.startDected == 1)
{
recevied_data.data = (recevied_data.data << 1) | 1;
counter++;
}
// zero is detected
else if((time > 1.1 && time < 1.5) && recevied_data.startDected == 1)
{
recevied_data.data = (recevied_data.data << 1);
counter++;
}
The entire code is attached bellow:
#include "stm32f4xx_hal.h"
#include <stdio.h>
#include "IR_struct.h"
#include "stm32f4xx_hal_def.h"
UART_HandleTypeDef UART2 = {0};
TIM_HandleTypeDef timerInstance;
uint32_t ARR;
const uint8_t time_interval = 100;
const uint16_t time_psc = 100;
volatile struct NEC_Protocol recevied_data = {0};
volatile uint8_t counter = 0;
volatile float time;
volatile uint16_t tim_Counter;
volatile HAL_StatusTypeDef status;
void led_Init(void);
void timer3_Init(uint16_t t, uint16_t psc);
void GPIO_Init(void);
void usart2_init();
void btn_Init(void);
void fillData();
int main()
{
HAL_Init();
GPIO_Init();
timer3_Init(time_interval, time_psc);
while(1)
{
if(recevied_data.complete) // a complete back is send
{
// do something
// reset it
HAL_Delay(20);
recevied_data.complete = 0;
recevied_data.startDected = 0;
counter = 0;
HAL_Delay(20);
}
}
}
void SysTick_Handler(void)
{
HAL_IncTick(); // time base of system (delay based on it)
}
void timer3_Init(uint16_t t, uint16_t psc){
// computation of ARR value, and RSC
uint32_t systemClockf = HAL_RCC_GetSysClockFreq();
ARR = t * (systemClockf / (1000 * (psc + 1))) - 1;
__HAL_RCC_TIM3_CLK_ENABLE();
timerInstance.Instance = TIM3;
timerInstance.Init.Period = ARR;
timerInstance.Init.CounterMode = TIM_COUNTERMODE_UP; // counts up
timerInstance.Init.Prescaler = psc;
timerInstance.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
// Init the timer
HAL_TIM_Base_Init(&timerInstance);
}
void GPIO_Init(void){
// configure the pin
GPIO_InitTypeDef GPIO;
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO.Pin = GPIO_EXTI_pin;
GPIO.Mode = GPIO_MODE_IT_FALLING;
GPIO.Pull = GPIO_NOPULL;
GPIO.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIO_EXTI_PORT, &GPIO);
GPIO.Pin = led_pin;
GPIO.Mode = GPIO_MODE_OUTPUT_PP;
GPIO.Pull = GPIO_NOPULL;
GPIO.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(led_port, &GPIO);
HAL_GPIO_WritePin(led_port, led_pin, 0);
HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI1_IRQn);
}
void fillData()
{
// turn on the led to notice the interrupt
//HAL_GPIO_WritePin(led_port, led_pin, 1);
// turn off the timer
tim_Counter = TIM3->CNT;
status = HAL_TIM_Base_Stop(&timerInstance);
// turn on the timer and set the counter = 0
TIM3->CNT = 0;
// calculate time
if(tim_Counter != 0)
{
time = ((float)tim_Counter / ARR)* time_interval; // caluclate time in ms
// start bit
if((time > 11.0 && time < 14.0) && recevied_data.startDected == 0) // start bit
recevied_data.startDected = 1;
// one is detected
else if((time > 2.0 && time < 2.5) && recevied_data.startDected == 1)
{
recevied_data.data = (recevied_data.data << 1) | 1;
counter++;
}
// zero is detected
else if((time > 1.1 && time < 1.5) && recevied_data.startDected == 1)
{
recevied_data.data = (recevied_data.data << 1);
counter++;
}
if(counter == 32)
{
recevied_data.complete = 1;
recevied_data.command = recevied_data.data >> 8; // get the command
recevied_data.address = recevied_data.data >> 24;
}
// turn off the led
//HAL_GPIO_WritePin(led_port, led_pin, 0);
}
if(counter < 32)
status = HAL_TIM_Base_Start(&timerInstance);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
HAL_GPIO_TogglePin(led_port, led_pin);
fillData();
}
void EXTI1_IRQHandler(){
HAL_GPIO_EXTI_IRQHandler(GPIO_EXTI_pin);
}
Header file
#ifndef IR_STRUCT_H_
#define IR_STRUCT_H_
#define GPIO_EXTI_pin GPIO_PIN_1
#define led_pin GPIO_PIN_5
#define led_port GPIOA
#define GPIO_EXTI_PORT GPIOB
struct NEC_Protocol{
uint8_t complete;
uint8_t startDected;
uint8_t command;
uint8_t address;
uint32_t data;
};
#endif /* IR_STRUCT_H_ */
I did not use the cubeMx to configure the modules.
Solved! Go to Solution.
2024-12-30 09:13 AM - edited 2024-12-30 09:14 AM
> The program is stuck in EXTI_ISR.
How do you know it's EXTI_ISR?
Observe SCB_ICSR.VECTACTIVE to find out which ISR is currently serviced. It may be a fault, too (probably HardFault). You are using float - do you have the FPU enabled?
JW
2024-12-29 12:05 PM
My thoughts: BTW: it is an assembler code instruction "b InfiniteLoop" (a brunch to itself, as endless loop).
This happens usually if you get an interrupt fired but there is not an INT Handler provided for this vector (the default one used).
I guess, potentially it is not the code you assume. It looks more like an INT gets active without a handler provided.
Is your TIM maybe configuring an INT (what is in HAL_TIM_Base_MspInit() ?), but the TIM IRQ Handler is missing?
Try to debug and check in the MCU/NVIC registers which INT vector was activated.
Remark:
It looks like you do the TIM launch inside the EXTI1_IRQHandler. Be careful: if some of the functions called, e.g. HAL_TIM_Base_Start(), use HAL_Delay() or check for elapsed/moving SYSTICK counter - it might not work.
You would need an INT when you are still in an INT Handler. So, the INT you wait for does not come (blocked by the still active INT Handler).
2024-12-29 11:35 PM
Thanks for your reply but I did not enable the timer interrupt so there should be no interrupt signal from the timer. But even when I enabled the timer interrupt and write the timer_ISR to clear the flag bit, and give it a priority of (0, 0) preamation, and subPriority the problem still the same. The program is stuck in EXTI_ISR.
2024-12-30 09:13 AM - edited 2024-12-30 09:14 AM
> The program is stuck in EXTI_ISR.
How do you know it's EXTI_ISR?
Observe SCB_ICSR.VECTACTIVE to find out which ISR is currently serviced. It may be a fault, too (probably HardFault). You are using float - do you have the FPU enabled?
JW
2024-12-30 05:31 PM
It is potentially not stuck in EXTI_ISR! It can be any INT coming but not an INTHandler provided for it.
Yes, it can be also due to using floating point and amusing to use HW FPU but not enabled (your compile options enable to use FPU but your code does not enable FPU).
I do not see a "division by zero" or a calculation resulting in an FPU error. Anyway: even the FPU can fire an error (when code tries to use it but not enabled on your startup).
Yes, you have to check which INT is triggered (it can be also a watchdog) and find the "missing INT handler".
Any INT fired which does not find an implementation of an INT Handler jumps to "DefaultHandler".
Please, check which INT was triggered. It is potentially one for which you have not implemented an INT Handler. The MCU registers, NVIC registers, will tell you what was the INT vector number (INT source).
Check your code generation settings: for instance: HW FPU to use but not set properly to enable to initialize FPU.
(there are macros, e.g. FPU_PRESENT, to do so)
2024-12-31 05:34 AM
Thanks everyone,
I have enabled the FPU and the code worked fine.
2024-12-31 10:26 AM
Great!