STM32F3 (Discovery) - need help with UART

I've lately been experimenting with the F0 series (STM32F030F4P6 in specific) without using the standard peripheral library; just direct register access (well I still use the basic core_cm0.h which has a few basic routines for the NVIC which I haven't bothered with doing direct register access for).

Getting the basic UART functional isn't particularly difficult (haven't done anything with flow control yet as I'm currently just using it for debug); do have a completely interrupt driven TX and RX with FIFO buffers - which I have tied to stdio for printf/scanf. An even more basic polling solution was even easier.

The procedure for basic polling UART is fairly simple:

  • Enable the USART as well as the GPIO port that contains the pins for your USART in the RCC (what pins are used for USART will depend on the USART and particular chip in use) - on the F0 I'm using it is PA9 and PA10.
  • configure the pins in the GPIO registers as being in alternate function mode - you will also need to select the appropriate alternate function number (look at the data sheet for the particular chip on the discovery board - that will have a table that lists the various alternate function mapping - on the F0 I'm using it ends up being AF1)
  • program the BRR register in the UART peripheral - this should have a value of your core speed divided by your baud rate - you need to select a baud rate that your other end is compatible with. You may not get an exact division - but you are generally ok as long as you are within a couple of percent.
  • enable the peripheral, as well as TX and/or RX, in the USARTs CR1 register.

For transmitting you then need to poll the TXE bit of USARTs ISR register, once that is set you can put the byte to be sent into the TDR register - writing to the TDR will automatically clear the TXE bit of the ISR register.

For receiving you would poll the RXIE bit of the ISR register, once that is set you can read the incoming byte from the RDR register.

Once you have the polling version working it isn't too difficult to work with the interrupts - at least if you've got the basic flow of the NVIC and interrupts figured out.

I could post some of my code for the F0, but I'm not sure it would be great for a few reasons:

  • it's for an F0 series chip - so you wouldn't be able to use it directly (while the USART peripheral is the same, not everything else is)
  • I've been doing something strange for the register access - more as an experiment than anything - in that instead of using their header with register definitions I've defined my own structures using C bitfields to access the various fields within each register. Some people think this is poor practice as the C standard doesn't fully specify the behaviour of how bitfields are packed and ordered and makes your code less portable. In this case I kind of disagree with the conventional wisdom here for two reasons - 1: the arm eabi defines handling of bitfields - this makes the layout and access of them consistent and predictable and 2: peripheral access code is inherently non-portable - as different chip families are not going to have the same peripherals making the portability points moot in my opinion. I plan on doing the same basic thing soon using more traditional register access at some point soon to compare the resulting differences in code size and speed - mostly what to see how much I'm trading off there for what I consider better readability.

TL;DR - I have some code that you may be able to use as a guide - but it isn't for that exact chip so it won't be usable directly; it's also written in a slightly unconventional manner. In a week or so I may have more conventional code to do the same thing. If you're really interested let me know and I can find somewhere to post it.

/r/arm Thread