2023-02-08 11:05 PM
I am writing code for the STM32F031K6T6 MCU using the Keil uVision. The IDE information is shown in the image below:
The C/C++ options for Target are configured as shown here:
I started a new project, selected the chip, and configured the run-time environment as below:
I initialized the clock and configured the Flash registers for the appropriate latency. I tested the frequency using MCO and it seems correct. I also initialized some GPIOs, UART, and the SysTick. The peripheral registered is modified as expected as seen on the System View for the respective peripheral in the debugging mode.
The problem is that some functions, such as functions for sending and receiving data via UART and some functions that use GPIO ports only work in debugging mode when I run the code line-by-line. If I click the run button the code gets stuck and the chip stops responding. I still see the VAL and CURRENT registers of the SysTick updating.
void System_Clock_init(void){
FLASH->ACR &= ~FLASH_ACR_LATENCY;
FLASH->ACR |= FLASH_ACR_LATENCY | 0x01;
RCC->CR |= RCC_CR_HSION;
while((RCC->CR & RCC_CR_HSIRDY) == 0);
RCC->CR &= ~RCC_CR_HSITRIM;
RCC->CR |= 16UL << 3;
RCC->CR &= ~RCC_CR_PLLON;
while((RCC->CR & RCC_CR_PLLRDY) == RCC_CR_PLLRDY);
RCC->CFGR &= ~RCC_CFGR_PLLSRC;
RCC->CFGR |= 10UL << 18;
RCC->CFGR &= ~RCC_CFGR_HPRE;
RCC->CFGR &= ~RCC_CFGR_PPRE;
RCC->CR |= RCC_CR_PLLON;
while((RCC->CR & RCC_CR_PLLRDY) == 0);
RCC->CFGR &= ~RCC_CFGR_SW;
RCC->CFGR |= RCC_CFGR_SW_PLL;
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
}
void UV_LED_Driver(uint32_t d){
for(uint32_t i = 0; i<16; i++){
if(d&(((uint32_t)0x8000)>>i)){
SDI2_ON;
}
else {
SDI2_OFF;
}
CLK2
}
LATCH2
}
// CLK2 -> PA5
// LE2 -> PA4
// SDI2 -> PA6
#define CLK2_OFF GPIOA->ODR |= (1UL << 5)
#define CLK2_ON GPIOA->ODR &= ~(1UL << 5)
#define LE2_OFF GPIOA->ODR |= (1UL << 4)
#define LE2_ON GPIOA->ODR &= ~(1UL << 4)
#define SDI2_ON GPIOA->ODR &= ~(1UL << 6)
#define SDI2_OFF GPIOA->ODR |= (1UL << 6)
#define CLK2 {CLK2_ON; us_Delay(1); CLK2_OFF;}
#define LATCH2 {LE2_ON; us_Delay(1); LE2_OFF;}
// CLK2 -> PA5
// LE2 -> PA4
// SDI2 -> PA6
void UV_LED_Driver_Init(void){
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
GPIOA->MODER &= ~((3UL << 8) | (3UL << 10) | (3UL << 12));
GPIOA->MODER |= ((1UL << 8) | (1UL << 10) | (1UL << 12));
GPIOA->OTYPER &= ~(0x70UL);
GPIOA->PUPDR &= ~((1UL << 8) | (1UL << 10) | (1UL << 12));
GPIOA->OSPEEDR &= ~((3UL << 8) | (3UL << 10) | (3UL << 12));
GPIOA->OSPEEDR |= ((1UL << 8) | (1UL << 10) | (1UL << 12));
GPIOA->ODR |= (0x70UL);
}
static uint32_t usDelay = 0;
void SysTick_init(uint32_t ticks){
SysTick->CTRL = 0;
SysTick->LOAD = ticks - 1;
NVIC_SetPriority(SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
SysTick->VAL = 0;
SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
}
void SysTick_Handler(void){
if(usDelay > 0){
usDelay--;
}
}
void us_Delay(uint32_t us){
usDelay = us;
while(usDelay != 0);
}
#define UV_LED_DRIVER(d) {for(int i = 0; i<16; i++){if(d&(0x000F>>i)){SDI2_ON;}else {SDI2_OFF;}CLK2}LATCH2}
#include <stm32f031x6.h>
#include "clock.h"
#include "LED_Driver.h"
#include "UART.h"
int main(void){
System_Clock_init();
Color_LED_Driver_Init();
UV_LED_Driver_Init();
Nucleo_Green_LED_Init();
UART_init();
SysTick_init(47);
//MCO_Init(); // Check PIN 18 (PA8) for the frequency of the MCO using an Oscilloscope
while(1){
UV_LED_DRIVER(~(0x0000)) // This runs well
//UV_LED_Driver((uint32_t)~(0x0000)); // If I run this line the debugger gets stuck here.
//It works if I run line-by-line
ms_Delay(100);
UV_LED_DRIVER(~(0xFFFF)) // This runs well
//UV_LED_Driver((uint32_t)~(0xFFFF)); // If I run this line the debugger gets stuck
//here. It works if I run line-by-line
ms_Delay(100);
}
}
Interestingly, if I define the functions as macros, they behave as desired. I finally tested the code on a STM32F429ZIT chip and it worked well, given the needed modifications in the initialization of the main clock and the GPIO.
Has anyone ever experienced anything similar or happens to know what could be causing this issue? I know that I could walk around this issue using CubeMX but I would like to find out what is causing this problem.
Thank you.
Solved! Go to Solution.
2023-02-08 11:44 PM
> SysTick_init(47);
This floods the mcu with systick interrupts. The execution of systick ISR when using -O0 takes more than 48 system ticks.
Leave the systick to run up to its maximum, and base the loopdelay on reading its value.
Additionally, you have to qualify usDelay as volatile.
JW
2023-02-08 11:12 PM
This is the main():
#include <stm32f031x6.h>
#include "clock.h"
#include "LED_Driver.h"
#include "UART.h"
int main(void){
System_Clock_init();
Color_LED_Driver_Init();
UV_LED_Driver_Init();
Nucleo_Green_LED_Init();
UART_init();
SysTick_init(47);
//MCO_Init(); // Check PIN 18 (PA8) for the frequency of the MCO using an Oscilloscope
while(1){
UV_LED_DRIVER(~(0x0000)) // This runs well
//UV_LED_Driver((uint32_t)~(0x0000)); // If I run this line the debugger gets stuck here.
//It works if I run line-by-line
ms_Delay(100);
UV_LED_DRIVER(~(0xFFFF)) // This runs well
//UV_LED_Driver((uint32_t)~(0xFFFF)); // If I run this line the debugger gets stuck
//here. It works if I run line-by-line
ms_Delay(100);
}
}
2023-02-08 11:44 PM
> SysTick_init(47);
This floods the mcu with systick interrupts. The execution of systick ISR when using -O0 takes more than 48 system ticks.
Leave the systick to run up to its maximum, and base the loopdelay on reading its value.
Additionally, you have to qualify usDelay as volatile.
JW
2023-02-09 12:42 AM
Absolutely correct. I just replaced the highlighted line with:
SysTick_init(479);
And all went well.
That explains why the code worked with the STM32F429ZI: that chip can run with a frequency of up to 180 MHz. It is not possible to enter and leave the ISR at the same speed in the SMT32F031. Of course!
Thank you and thanks for the additional tip about the volatile keyword.
Best.
Thiago.
2023-02-09 01:08 AM
One more thing: don't use GPIO_ODR, use GPIO_BSRR. The performance is the same, but using GPIO_BSRR is safe in interrupt context (atomic).
JW
2023-02-09 01:16 AM
Interesting. Thanks for that info too. I always used the ODR and didn't know about the atomic feature of the BSRR.