cancel
Showing results for 
Search instead for 
Did you mean: 

First steps with STM bare metal, UART not working [STM32VLDiscovery]

Jesus Tomas
Associate
Posted on February 25, 2016 at 16:09

First of all, let me apologize in advance for the mistakes in my grammar. Not an english speaker here. I hope, howewer, that this can be understood.

I have recently started to move away from PIC microcontrollers (Mainly PIC18F family) to ARM microcontrollers. I chosed STM32 because of the inexpensive Discovery Boards, wich I could use before doing a board for the project I need to do. I saw that some libraries could be used, but back in the day when I was first learning about microcontrollers, teacher never allowed us to use anything complex, since it ''obscured'' what happened in the microcontroller. Those were good times, learning in ASM with small microcontrollers... Anyway, now, some ten years after that, I still like to do things ''as close to the action'' as I can. So, I found this tutorial for setting up GNU GCC in Keil [

http://m8blogspot.com.es/2012/10/using-gcc-in-keil-best-of-both-worlds.html

] and made it work with some minor changes (Only in preprocessor directives I had to change anything, I think, and there is not much difference between Keil 4 and 5 versions). I had some problems but as of now, I have GPIOs working, and SysTick happily generating ticks every ten ms. Now I am trying to set up one of the UARTs, since withthat done I find easy to develop the rest (Having the possibility to send messages to the PC makes easier to follow the program flow, specially since I am not confortable enough with the debuggin way...). Seems that I can't send anything (Not reading even garbage from the PC), and I have not a oscilloscope right now with me, so, if any person more experienced with STM32 mcus could take a look at this and enlighten me, that would be great. The code: USART configuration

void ConfigUSART2(void)
{
// Pins: UART2_TX is PA2, UART2_RX is PA3
// So PA2 ==> ''alternate function push-pull''
// PA3 ==> ''Input floating''
GPIOA->CRL &= 0xFFFF00FF; // Both nibbles to zero
GPIOA->CRL |= 0x00004200; // and now to the correct values
RCC->APB1ENR |= RCC_APB2ENR_AFIOEN; // AFIO Clock
RCC->APB1ENR |= RCC_APB1ENR_USART2EN; //USART2 Clock
//Following the steps described in page 582 of RM0041:
USART2->CR1 |= USART_CR1_UE; // Step 1: Enable USART
//Step 2: M value, I want 8 bits so no need to touch it
//Step 3: Stop bits, again default value is ok
//Step 4: Not using DMA, so...
USART2->BRR = 0xC9; //Step 5: Baudrate --> Baudrate=Fclk/(15*USARTDIV) --> With 24MHz, 115200 USARTDIV=12,9
USART2->CR1 |= USART_CR1_TE; //Step 6: IDLE
USART2->CR1 |= USART_CR1_RE; //I enable also reception
}

Main

int main()
{
unsigned long i;
uint8_t transmit, receive, data;
Inicializar_GPIOs(); // This congigures GPIOs for leds and pushbutton, working OK
Inicializar_SysTick(); // Again, working OK, this configures SysTick only
ConfigUSART2();
transmit=0; 
receive=0;
while(1)
{
if(GPIOA->IDR & 1) // Button pressed
{
// PC9 led Toggle
GPIOC->ODR ^= GPIO_ODR_ODR9;
//Dummy loop
for(i=0;i<
0x1FFFFF
;i++); 
}
if (transmit<10)
{
data
= 
0x48
;
data+=transmit;
//while(USART2->SR&USART_SR_TXE);// Wait for idle
USART2->DR = dato;
transmitido++;
GPIOC->ODR ^= GPIO_ODR_ODR9;
for(i=0;i<
0x1FFFFF
;i++);
for(
i
=
0
;i<0x1FFFFF;i++);
}
if (USART2->SR&USART_SR_RXNE) //Data ready to be read
{
receive=USART2->DR;
if (receive==data)
{
GPIOC->ODR |= GPIO_ODR_ODR9; //I leave Led always on and wait
while(1);
}
}
}
}

I have translated variables names and comments to english,I hope there is no mistakes... Thanks in advance! And also, do you know any good tutorial/book for programming this mcus bare metal? #limited-thinking
22 REPLIES 22
Posted on February 25, 2016 at 20:03

USART2->BRR = 0xC9; //Step 5: Baudrate --> Baudrate=Fclk/(15*USARTDIV) --> With 24MHz, 115200 USARTDIV=12,9

No, USART2->BRR = 24000000 / 115200;

24000000 / 201 = 119402.99 +3.65%

24000000 / 208 = 115384.62 +0.12%

This would of course assume that the chip is running at 24 MHz via the PLL settings, and not directly off the HSI/HSE at 8 MHz.

Would suggest sending a stream of U characters, and scope the signal to confirm the baud rate and bit timings.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Radosław
Senior
Posted on February 25, 2016 at 20:09

1. Look to errata, small delay is needed after clock enabling if peripheral access is next.

2. Peripheral enable should be after initialization. (search notes to bit definition).

3.

for(

i

=

0

;i<0x1FFFFF;i++); // this will not work. Optimization will cut this delay off. Use volatile keyword.

4. This is F1 family? Check port and alternate function configuration.

5. don't work becose :

RCC->APB1ENR |= RCC_APB2ENR_AFIOEN; wrong register 6. BRR = (USART_CLK = PLCK)/BAUDRATE; (simply math) 

Posted on February 25, 2016 at 20:10

I'm not a huge fan of this type of coding.

This is a good guide to using the VL Discovery

http://www.cs.indiana.edu/~geobrown/book.pdf

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Radosław
Senior
Posted on February 25, 2016 at 20:15

1. clive1 SPL?  :\ ugly and hate this at this moment dead library.

2. A suggest to put away F1 family. Ugly GPIO configuration. Old core revision with bad stack aligment. 

Posted on February 25, 2016 at 21:57

Well it's better than the POS alternative that has been provided to replace it. Added to that it rather colours one view of the ''10 Year Commitment''

Yes, I'd agree that the F1 VL series is rather dated at this point. Pick a Nucleo board for something more recent.

Unless the USART pins are being remapped the AFIO probably has little impact.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Jesus Tomas
Associate
Posted on February 26, 2016 at 09:07

Thank you all guys for the help. Updating now:

About the baudrate: I will use the simple formula you gave. Don't understand why they gave something much more complex in the datasheet, anyway.

RCC->APB1ENR |= RCC_APB2ENR_AFIOEN; wrong register

--> Too much hours working and doing so without coffee... that can do strange things to one's mind :D

for(i=0;i<0x1FFFFF;i++); // this will not work. Optimization will cut this delay off. Use volatile keyword

. --> I will have this in mind, anyway, no optimizations at the moment (In fact, that delay is working. When you say ''use volatile keyword'' mean in the variable declaration (I mean, declaring i as volatile) or anything else?

This is F1 family? Check port and alternate function configuration. --> Checked again. If datasheet is correct, should be ok. Anyway I will do some test, now that I have here the scope.

I'm not a huge fan of this type of coding

.--> With smaller micros I was, but starting to wonder if this is a good idea with this beasts

2. A suggest to put away F1 family. Ugly GPIO configuration. Old core revision with bad stack aligment.

Yes, I'd agree that the F1 VL series is rather dated at this point. Pick a Nucleo board for something more recent.

- Well, old often mean ''more tried'' (I mean that there are less bugs to discover, more support/examples/libraries out there...). I will take a look at these Nucleo boards, but this family did not look that bad. Mostly my problem is trying to follow the procedures I used to, when this is a completely different microcontroller... I hoped that modules will be similar, but the have very little in common (I mean, eveng GPIOs envolve a lot of registers...)

Anyway, if I give up on this bare metal approach, any suggestions? Should I go for standard libraries? Will they give same kind of problems if I stick to STM32F1x micros?

I did a board to prototype a design even after starting to tinker with the discovery board (I only picked this to do some work before PCBs come and I can mount them) and I will not like to waste it, so I will look if there is any other micro that can fit in (Once again, with Microchip Pics you had a lot of parts and often could replace one with another with minimal changes... I hope this can be done with STM32 too...)

Ah, and with the scope on, TX pin does not even go up, so pin is not configured right, or module is not enabled...

EDIT: Ok, I spotted another mistake, configured TX as GPIO and not AFIO...

changed that but still not seeing even TX go high while idle...

Forget that, It works (I put it as open drain instead of pull-push when I changed from GPIO to AFIO...)

I should be able to make it work now, but I will be very happy to hear what you have to say about what families, libraries, even compilers or IDEs are best to start with. Thank you all.
Posted on February 26, 2016 at 18:45

The F1 SPL is very solid. I think our collective concern here is that the F1 design is rather awkward, subsequent families implemented things better, like the GPIO AF multiplexor at a pin rather than peripheral level.

My concern with someone learning a decade old architecture is that it is a less valuable career move, learn the current stuff and be forward looking.

Register level coding has it's place, but it is not easy to pull off, and usually not dramatically more efficient. A compiler can't fold multiple load/store operations on volatile variables. Code that initializes something once doesn't need to be optimal, but it needs to be right. You can mix methods and use direct register techniques where the code is heavily utilized. There is a lot of bit level minuta that isn't particularly portable, and plenty of pitfalls. If you want to spend hours digging through code, especially other people's code, or stuff you haven't touched in a year, to pick out the bit that's wrong, or miss copied from another peripheral, then have at it. Some people are well suited to this coding method, I can and have used this method, but I can code and debug fast by letting the computer deal with the minuta. If you have a photographic memory and like imprinting reference manuals, it's probably ideal. 

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Radosław
Senior
Posted on February 26, 2016 at 19:05

clive1 very bad thinking.  i very ofter heard that profesional guys not use any library.

What about const corectness?   etc?

I do many test. SPL give me more than 30% ovesized code. 30% slover. And aplikaction uses more that 10% energy. (i'm usualy create low power aplication). Learning SPL knowage about architekture isn't important? 

I see meny  programs using SPL. this is ugly shity code, and meny of this aplication don't work after optimization.

At end.  SPL is dead. Why someone should learn this?

Mcu is for electronic guys not for programist thay prefer aplication units. .

AvaTar
Lead
Posted on February 27, 2016 at 10:45

>clive1 very bad thinking.

Have you ever tried to run same source code base on a Cortex M, a C166 (8051 compatible) and a Fujitsu FR MCU ? Obviously not.

You need to understand that there are certain branches were register hacking is proscribed, however successful it is for you personally.