2019-07-16 07:34 PM
Hello,
I need your help to recognize my issue correctly, please help me,
background:
I am having trouble using the stm32l053RB NUCLEO development board for USB protocol parsing.
issue:
When using timer to generate PWM, once the USB receive data is configured, the PWM waveform frequency will be greatly reduced.
Also when using the timer to generate a timed interrupt, once the USB work is configured, the CNT data will be stuck, and the timer will stop unless the USB is reset.
I have tried all the timers of this chip and will have the same problem.
Why is this happening, does USB work affect the clock of TIMER?
if you can help to solve issue or give any advice, I am very thankful for your kindness in advance.
Thanks.
my email is jysong@mindpointeye.com
Solved! Go to Solution.
2019-07-28 07:53 PM
Thank you very much for your guidance.
This problem has been solved by closed USB low_power_enable.
Bit 2 LP_MODE: Low-power mode
This mode is used when the suspend-mode power constraints require that all static power
dissipation is avoided, except the one required to supply the external pull-up resistor. This
condition should be entered when the application is ready to stop all system clocks, or
reduce their frequency in order to meet the power consumption requirements of the USB
suspend condition. The USB activity during the suspend mode (WKUP event)
asynchronously resets this bit (it can also be reset by software).
0: No Low-power mode.
1: Enter Low-power mode.
2019-07-17 08:09 AM
You gave us little information, but I guess you attempt to run timer interrupts at a very high rate (too often), or the timer's Interrupt Service Routine (ISR) is too long.
JW
2019-07-17 07:16 PM
@Community member
Thank you very much for your reply and suggestions.
Using the timer to generate the PWM waveform does not require timer's Interrupt Service Routine (ISR), but after the USB work, the PWM waveform frequency is from the original 1.316KHz changed to 2.718Hz, So I think this problem should be independent of the timer's Interrupt Service Routine (ISR).
I also tried to generate low-frequency PWM waveforms. The problem encountered after USB work is the same.
I am sorry for the small amount of information I provided.
The main function code is as follows:
int main(void)
{
/* Buffer used for USB transmission/reception*/
uint8_t usb_send[4], usb_recive[4];
HAL_Init();
/* Configure the system clock to get correspondent USB clock source */
SystemClock_Config();
/* Init Device Library */
USBD_Init(&USBD_Device, &HID_Desc, 0);
/* Register the HID class */
USBD_RegisterClass(&USBD_Device, &USBD_HID);
/* Start Device Process */
USBD_Start(&USBD_Device);
USBD_LL_PrepareReceive(&USBD_Device, HID_EPOUT_ADDR, usb_recive, 4);
/* Compute the prescaler value to have TIM2 counter clock equal to 16 MHz */
uwPrescalerValue = (SystemCoreClock / 16000000) - 1;
tim = 2;//TIM2产生4channelPWM TIM21/22产生2channel PWM
period_vl = 1600 - 1;
pulse_vl[0] = 1200;
pulse_vl[1] = 800;
pulse_vl[2] = 533;
pulse_vl[3] = 400;
channel = 1;
pwm_init(tim, period_vl);
pwm_enable(channel++, pulse_vl[0]);
}
static void pwm_init(uint8_t time, uint16_t period)
{
switch (tim) {
case 2:
TimHandle.Instance = TIM2;
break;
case 21:
TimHandle.Instance = TIM21;
break;
case 22:
TimHandle.Instance = TIM22;
break;
default:
Error_Handler();
}
TimHandle.Init.Prescaler = uwPrescalerValue;
TimHandle.Init.Period = period;
TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
if(HAL_TIM_PWM_Init(&TimHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/*##-2- Configure the PWM channels #########################################*/
/* Common configuration for all channels */
sConfig.OCMode = TIM_OCMODE_PWM1;
sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfig.OCFastMode = TIM_OCFAST_DISABLE;
}
static void pwm_enable(uint8_t channel, uint16_t pulse)
{
uint32_t pwm_channel;
if (channel > 4)
Error_Handler();
if ((TimHandle.Instance != TIM2) && (channel > 2))
Error_Handler();
switch (channel) {
case 1:
pwm_channel = TIM_CHANNEL_1;
break;
case 2:
pwm_channel = TIM_CHANNEL_2;
break;
case 3:
pwm_channel = TIM_CHANNEL_3;
break;
case 4:
pwm_channel = TIM_CHANNEL_4;
break;
default:
Error_Handler();
}
sConfig.Pulse = pulse;
if(HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, pwm_channel) != HAL_OK)
{
/* Configuration Error */
Error_Handler();
}
if(HAL_TIM_PWM_Start(&TimHandle, pwm_channel) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
}
2019-07-17 10:44 PM
I don't know if this is the culprit, but main() in microcontrollers should never return, it should end with an endless loop. The program then should remain in this loop, and should never get into the hardfault handler.
JW
2019-07-17 10:55 PM
I am sorry for this mistake, I missed the while(1) loop when I intercepted the code.
The complete code is as follows:
int main(void)
{
/* Buffer used for USB transmission/reception*/
uint8_t usb_send[4], usb_recive[4];
#ifdef I2CEN
/* Buffer used for I2C transmission/reception*/
uint8_t i2c_tx[4], i2c_rx[2], count;
#endif
#ifdef PWMEN
/* pwm parameter */
uint16_t period_vl, pulse_vl[4];
uint8_t channel;
#endif
HAL_Init();
/* Configure the system clock to get correspondent USB clock source */
SystemClock_Config();
/* Configure Key button for remote wakeup */
/* Init Device Library */
USBD_Init(&USBD_Device, &HID_Desc, 0);
/* Register the HID class */
USBD_RegisterClass(&USBD_Device, &USBD_HID);
/* Start Device Process */
USBD_Start(&USBD_Device);
USBD_LL_PrepareReceive(&USBD_Device, HID_EPOUT_ADDR, usb_recive, 4);
#ifdef I2CEN
//if(usb_recive[0]==1) {
i2c = 2;
i2c_tx[0] = 0x92;
i2c_tx[1] = 0x02;
i2c_tx[2] = 0x42;
i2c_tx[3] = 0x00;
count = 2;//register value size
I2c_init();
I2c_read(i2c_tx, i2c_rx, count);
I2c_write(i2c_tx, count);
I2c_read(i2c_tx, i2c_rx, count);
usb_send[0] = i2c_rx[0];
usb_send[1] = i2c_rx[1];
#endif
#ifdef PWMEN
/* Compute the prescaler value to have TIM2 counter clock equal to 16 MHz */
uwPrescalerValue = (SystemCoreClock / 16000000) - 1;//16000000
tim = 2;//TIM2产生4channelPWM TIM21/22产生2channel PWM
period_vl = 3200 - 1;
pulse_vl[0] = 2400;
pulse_vl[1] = 1600;
pulse_vl[2] = 1040;
pulse_vl[3] = 800;
channel = 1;
pwm_init(tim, period_vl);
pwm_enable(channel++, pulse_vl[0]);
pwm_enable(channel++, pulse_vl[1]);
pwm_enable(channel++, pulse_vl[2]);
pwm_enable(channel++, pulse_vl[3]);
#endif
#ifdef WGEN
TIM_Init();
if(HAL_TIM_Base_Start_IT(&TimHandle_WG) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
wiegand_init();
/* -2- Configure EXTI Line13 (connected to PC13 pin) in interrupt mode */
EXTILine4_15_Config();
while(1) {
if(WGResult.update) {
WGResult.readNum++;
WGResult.update = 0;
}
}
#endif
#ifdef GPIOEN
BSP_LED2_Init(LED2);
BSP_LED2_On(LED2);
EXTILine4_15_Config();
#endif
USBD_LL_Transmit (&USBD_Device, HID_EPIN_ADDR, usb_send, 1);
//}
while (1) {
}
}
2019-07-17 11:04 PM
Well, I don't have any specific advice - you'd need to debug this in the same way as with any other code.
Make sure the code does not jump into the hardfault handler.
If some of the timer's register content changes during USB operation, you may want to place a data breakpoint onto that register in the debugger, that should help to find out which code changed it.
JW
2019-07-17 11:24 PM
Thanks for your suggestion, I will continue to debug in this direction.
Now I have some questions about the TIMER clock source and need your guidance.
When I calculate the divider value of timer, SystemCoreClock is 16Mhz.
uwPrescalerValue = (SystemCoreClock / 16000000) - 1, the TIMx_PSC register Is setted to 0 ;
But when I actually calculate the main frequency according to the frequency of PWM waveform, the result is 32.768Khz*2^6;
Why is there such a difference, which value is the clock source of the timer?
This may be a stupid question, but I need your help to understand the problem.
Thanks!
2019-07-18 02:18 AM
That depends on which oscillator has been chosen as the system clock source, its setting, and then setting of the respective APB prescaler.
JW
2019-07-21 09:01 PM
Hi JW,
I spent some time on the systemClock_Config of the STM32L053R8.
When the TIMER and USB work at the same time, the problem of the timer counter has been repositioned.
Please take a moment to help analyze;
After SystemClock_Config,The RCC register as follow
If run with breakpoint,the RCC register will modify the configuration correctly. Once run without breakpoint,
RCC register will be cleaned as follow:
Urgently need your help, if you need additional information or need to reproduce this problem, please feel free to contact me.
The configs as follows:
static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE();
/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Enable HSI Oscillator and activate PLL with HSI as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSEState = RCC_HSE_OFF;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4;
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV2;
RCC_OscInitStruct.HSICalibrationValue = 0x10;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
}
PS:In the case of USB or TIMER only, the system clock configuration has been tested and is working properlyand.
2019-07-21 11:58 PM
I have no idea what could cause such change in RCC/system clock settings. It's very unusual for the system clock to be changed during run. Again, you may want to set data breakpoint on some of the RCC registers to see, which part of the code causes the changes.
JW