2020-05-26 01:57 AM
Hello community,
I have a strange behaviour with my timer. Well probably it is not strange but the problem sits between keyboard and mouse, but hopefully you can help me find the cause.
following the setup of my program:
I use STM32F4 on a self-created board (well, develeped by a collegue), atollic truestudio, the HAL libraries and systick option. (firmware was created by that colleague as well who has left our company).
My goal is the following:
send a command via usb (working) to init my sensor system (working), then start the actual program/routine which includes:
starting timer with approx 256hz, with every hit of the timer interrupt (ISR) sample data until I have 256 samples (all working), calculating fft (working), sending results out over usb (working), set a counter which decrements in systick function (working), when counter reaches "0" restart the timer (probably not working) and get next samples (NOT working).
Precisely: the ISR, where I sample my data, is not hit anymore.
I try to post the relevant code:
void init_machsens(int CI_INTERFACE)
{
//init-routine
}
void start_machsens(int CI_INTERFACE)
{
if (MEAS_MODE < 1)
{
for (PCounter1 = 0; PCounter1 < CI_PART_LENGTH; PCounter1++)
{
EXEC_PARAM2[PCounter1] = '\0';
}
strncpy((char*)EXEC_PARAM2, "FFT", 3);
MX_TIM11_DeInit();
MX_TIM11_Init();
adc_measurement();
menu_update(); //updates an epaper-display
CONT_MEAS_COUNTER = 200; //each 2s new measurement
}
switch(CI_INTERFACE)
{
case 0: break;
case 1: USB1_TRANSFER = TRUE;break;
case 2: USB2_TRANSFER = TRUE;break;
case 3: ETH1_TRANSFER = TRUE;break;
case 4: USART1_TRANSFER = TRUE;break;
case 5: USART3_TRANSFER = TRUE;break;
case 6: USART6_TRANSFER = TRUE;break;
default: break;
}
}
void adc_measurement(void)
{
//get 256 FFT_Samples:
HAL_TIM_Base_Start_IT(&htim11);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_RESET); //testpin for oszi
TIM11_COUNTER = 0;
while(TIM11_COUNTER < 256);
HAL_TIM_Base_Stop_IT(&htim11);
//prepare raw data for fft calculation
calc_rfft_values(1);
calc_rfft_values(2);
calc_rfft_values(3);
//prepare USB_OUT_DATA
CDC_Transmit_HS((uint8_t *)USB_OUT_DATA, (USB_COUNTER));
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == htim11.Instance)
{
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_SET);
//start ad conversion:
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_SET); //SPI2
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_RESET); //SPI2
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_11, GPIO_PIN_SET); //SPI4
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_11, GPIO_PIN_RESET); //SPI4
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_5, GPIO_PIN_SET); //SPI5
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_5, GPIO_PIN_RESET); //SPI5
// ADC_X ready?
while(HAL_GPIO_ReadPin(GPIOI, GPIO_PIN_3))
{
}
// ADC_Y ready?
while(HAL_GPIO_ReadPin(GPIOI, GPIO_PIN_2))
{
}
// ADC_Z ready?
while(HAL_GPIO_ReadPin(GPIOI, GPIO_PIN_1))
{
}
transfer_SPI2(2, 3, SPI_NO_CS);
transfer_SPI4(2, 3, SPI_NO_CS);
transfer_SPI5(2, 3, SPI_NO_CS);
FFT_SampleX[TIM11_COUNTER][0] = SPI2_TRANSFER_RX[0];
FFT_SampleX[TIM11_COUNTER][1] = SPI2_TRANSFER_RX[1];
FFT_SampleX[TIM11_COUNTER][2] = SPI2_TRANSFER_RX[2];
FFT_SampleY[TIM11_COUNTER][0] = SPI4_TRANSFER_RX[0];
FFT_SampleY[TIM11_COUNTER][1] = SPI4_TRANSFER_RX[1];
FFT_SampleY[TIM11_COUNTER][2] = SPI4_TRANSFER_RX[2];
FFT_SampleZ[TIM11_COUNTER][0] = SPI5_TRANSFER_RX[0];
FFT_SampleZ[TIM11_COUNTER][1] = SPI5_TRANSFER_RX[1];
FFT_SampleZ[TIM11_COUNTER][2] = SPI5_TRANSFER_RX[2];
TIM11_COUNTER++;
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_RESET);
}
}
void Systick_Command(void)
{
// IWDG Reload (IWDG is set to 8 seconds)
HAL_IWDG_Refresh(&hiwdg);
// ADC Measurement Continuous
if (CONT_MEAS_COUNTER > 1)
{
CONT_MEAS_COUNTER--;
}
if ((CONT_MEAS_COUNTER > 0) && (CONT_MEAS_COUNTER < 2))
{
if (strstr((char*)EXEC_PARAM2, "FFT") > 0)
{
adc_measurement(); //dauert langsam 1,065s
display_update(); //dauert 485ms
CONT_MEAS_COUNTER = 200; // Each Shot any 2s
}
}
}
/* TIM11 init function */
void MX_TIM11_Init(void)
{
htim11.Instance = TIM11;
htim11.Init.Prescaler = 3360; // htim11.Init.Prescaler = 3360; //168MHz * 20
htim11.Init.CounterMode = TIM_COUNTERMODE_UP;
// Set the Init Parameter
//TIM11_INIT_PERIOD = 40000 / FH5401_FREQ;
htim11.Init.Period = TIM11_INIT_PERIOD;
htim11.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_Base_Init(&htim11) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/*
if (HAL_TIM_OnePulse_Init(&htim11, TIM_OPMODE_SINGLE) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
} */
//HAL_TIM_Base_Start_IT(&htim11);
}
with the help of the E5-pin watching on an oscilloscope I figured out that the program hangs on the while(TIM11_COUNTER<256) routine. The program is then cancelled by watchdog.
Another approch whicht I tried, was, to start the timer in the init function and control the execution of the data sampling with a special setting of the TIM11_COUNTER variable. But still, the ISR is not hit when starting the adc_measurement() out of the systick routine.
So far, the information I could provide at this point. If you need more, please let me know!
Is there some problem, that systick oder usb confuses the timer11? Actually I searched through the firmware for any other existance of timer11 and found none.
I would be very happy if you'd share any idea where I could dig for the problem. Thank you in advance for your time and help.
Greetings,
Annika
2020-05-26 08:42 AM
if i understand rightly, when timer11 was shot 255 times. it stops and starts again only when systick_command called, then timer doesn't shoot anymore ? (sorry i have bad English so i need to rephrase)
1) first of all i truly recommend check TIM11->CNT register. It should increase after HAL_TIM_Base_Start_IT. then if it doesn't increment you can try to create sample without USB and other periph. e.g .
2) Can you check another TIM e.g 7.
p.s I create simple example with TIM7 on L071 chip (i doesnt have another) and stop/start tim_irq work well
void TIM11_IRQHandler()
{
HAL_TIM_IRQHandler(&htim11);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == htim11.Instance)
{
TIM11_COUNTER++;
}
}
static void MX_TIM11_Init(void)
{
/* USER CODE BEGIN TIM11_Init 0 */
/* USER CODE END TIM11_Init 0 */
/* USER CODE END TIM11_Init 1 */
htim11.Instance = TIM11;
htim11.Init.Prescaler = 3360;
htim11.Init.CounterMode = TIM_COUNTERMODE_UP;
htim11.Init.Period = TIM11_INIT_PERIOD ;
htim11.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim7) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM11_Init 2 */
HAL_NVIC_SetPriority(TIM11_IRQn, 1, 1);
HAL_NVIC_EnableIRQ(TIM11_IRQn);
/* USER CODE END TIM11_Init 2 */
}
void main(){
HAL_Init();
SystemClock_Config();
MX_TIM11_Init();
while (1)
{
/* USER CODE END WHILE */
HAL_TIM_Base_Start_IT(&htim11);
TIM7_COUNTER = 0;
while(TIM11_COUNTER < 256)
{
}
HAL_TIM_Base_Stop_IT(&htim11);
/* USER CODE BEGIN 3 */
}
return 0;
}
2020-05-29 05:01 AM
thanks for these suggestions.
I tried with a different timer (tim7), but same problem.
concrete:
timer gets restartet and increments/updates counter register but interrupt does not get fired.
I did not manage to view the counting with the debugger, because debugger crashes when i try to establish usb connection. But I saved the values from the counting register and sent them out via usb.
for(PCounter = 0; PCounter<9; PCounter++)
{
timecheck[PCounter] = 0;
}
htim7.Instance->CNT = 0;
HAL_TIM_Base_Start_IT(&htim7);
time1 = htim7.Instance->CNT;
for(PCounter = 0; PCounter<30000; PCounter++)
{
time_send=1; //dummy for the loop
}
time2 = htim7.Instance->CNT;
for(PCounter = 0; PCounter<50000; PCounter++)
{
time_send=1;
}
time3 = htim7.Instance->CNT;
HAL_TIM_Base_Stop_IT(&htim7);
I get plausible values for time1, time2 and time3. and interrupt should occur once, but I did not recognize anything.
any other ideas out there?
2020-05-29 05:11 AM
Write a simple but complete compilable example demonstrating the problem.
JW
2020-05-29 07:08 AM
try with simple sample like above (where only timer was used). Add pin debug with oscilloscope or led on irq.