cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L151C8T6 USART1 works from time to time

kaloyan
Associate III

Hello.

I'm using STM32L151C8T6 for some simple task. In the beginning I used MSI clock and everything was fine. But I decided to switch to HSI and now I got problems using USART1, namely I think that the USART1 periphery isn't properly initialized due to some clock problem.

If I use the debugger and I'm watching the USART1 registers, then my program works fine. If I switch to monitor the CPU registers for example, then my program got stuck in my implementation of fputc(). All data for the USART1 registers is 0x00. I guess that something went wrong moving my code to HSI from MSI. Below is the code.

void main() {
	sysinit();
	Dummy_USART_Init(); // #include "usart.h"
	setupIWDG();
	IWDGReset = isIWDGReset();
 
	//some code to read/write variables from the EEPROM
 
	while(1) {
/*...*/
}
}
 
void sysinit() {
	RCC_DeInit();
	RCC_HSICmd(ENABLE); //16MHz, ADC requirement 	// TODO: The ADC HSI need at least 1.5V core!! check for bugs! BUGBUG
	while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
	RCC_SYSCLKConfig( RCC_SYSCLKSource_HSI ); // MSI, HSI, HSE or PLL
    while(RCC_GetSYSCLKSource() != 0x04);
	RCC_HCLKConfig( RCC_SYSCLK_Div1 ); //  AHB clock = SYSCLK 
 
	RCC_PCLK1Config( RCC_HCLK_Div1 );
	RCC_PCLK2Config( RCC_HCLK_Div1 ); //RCC_HCLK_Div1: APB2 clock = HCLK (from AHB clock)
 
	//RCC_PLLConfig( RCC_PLLSource_HSI_Div2, RCC_PLLMul_6 );
	//RCC_PLLCmd( ENABLE );
	//RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK ); //use PLL as the SYSCLK clock source
 
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); //MISC in the help file...
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	RCC_ClocksTypeDef workingFreq;
	RCC_GetClocksFreq(&workingFreq);
	systicks = workingFreq.SYSCLK_Frequency / 1000;
	SysTick_Config(systicks); //ticks - number of ticks btw. 2 interrupts
	if(workingFreq.SYSCLK_Frequency > 1000000) {
		sysTicksPerMs = systicks/(workingFreq.SYSCLK_Frequency/1000);
	}
}
void Dummy_USART_Init() {
	RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA, ENABLE );
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1, ENABLE );
 
	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //push-pull output
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz; //400kHz, 2,10,40 MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Init( GPIOA, &GPIO_InitStructure );
 
	GPIO_PinAFConfig( GPIOA, GPIO_PinSource9, GPIO_AF_USART1 );
	GPIO_PinAFConfig( GPIOA, GPIO_PinSource10, GPIO_AF_USART1 );
 
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	
	USART_DeInit( USART1 );
	USART_Init( USART1, &USART_InitStructure );
	USART_Cmd( USART1, ENABLE );
}

Any advises would be helpful!

Edit: here is the fputc()

int fputc(int ch, FILE * f) { //file is defined in stdio.h; set library configuration to FULL
  while( USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET );
  USART_SendData( USART1, (unsigned int) ch );
  return ch;
}

 The TC and TXE flags in USART1 are always 0.

5 REPLIES 5

If all registers are zero, check the clocking of the peripheral. User the debugger to inspect RCC, GPIO, and UART registers.

Make sure to check for, and clear, any parity, noise or framing error for reception.

Sitting in tight loops might be problematic if there is a watchdog.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
berendi
Principal

Either the core voltage or the flash wait state should be increased before setting HSI as the clock source.

0690X00000BvZPdQAN.png

Start reading at the Dynamic voltage scaling management chapter of the reference manual.

kaloyan
Associate III

At the end of the while() loop I'm calling sysinit() and Dummy_USART_Init() again because if the Vdd drops below some level, the MCU enters STOP mode. I commented out RCC_DeInit() in the beginning of sysinit() and now the MCU runs much more stable. (I was getting hard faults, and now I'm still waiting for one). Also I had another minor bug that probably was the reason for the stuck in fputc().

Thanks a lot! I knew I had to verify Vdd and the wait states, but to be honest I was lazy to do that. However my excuse is that the MCU runs at 16 MHz and Vdd is 3.5V when debugging. Despite that your comment is pretty important to be kept on mind.

The other bug was if statement as follows:

if( SysTickVar < basicTimer )
	IWDG_ReloadCounter();
	continue;

I added IWDG_ReloadCounter() and forgot to add the {} brackets. basicTimer stood with value 0 and the consequences of that are obvious.