Skip to content

Instantly share code, notes, and snippets.

@DaveRichmond
Created December 1, 2012 07:20
Show Gist options
  • Select an option

  • Save DaveRichmond/4180948 to your computer and use it in GitHub Desktop.

Select an option

Save DaveRichmond/4180948 to your computer and use it in GitHub Desktop.
STM32F2 USART
#include "drivers/serial.h"
#include <stm32f2xx.h>
#include <stdio.h>
#pragma import(__use_no_semihosting_swi)
struct __FILE {
int handle;
};
FILE __stdout;
FILE __stdin;
#define usart serial_USART1
void retarget_init(void){
serial_init(usart, 115200);
}
int fputc(int c, FILE *f){
if(c == '\n') fputc('\r', f);
while(serial_putc(usart, c) == false);
return c;
}
int fgetc(FILE *f){
int c;
while((c = serial_getc(usart)) == -1);
return c;
}
void _ttywrch(int c){
fputc(c, &__stdout);
}
void _sys_exit(int return_code){
while(1);
}
#include <stdlib.h>
#include "ringbuffer.h"
void ringbuffer_init(ringbuffer_t *buffer, uint16_t size){
buffer->in = 0;
buffer->out = 0;
buffer->size = size;
buffer->buffer = malloc(size);
}
void ringbuffer_deinit(ringbuffer_t *buffer){
if(buffer->size == 0) return;
free(buffer->buffer);
buffer->in = 0;
buffer->out = 0;
buffer->size = 0;
}
bool ringbuffer_isfull(ringbuffer_t *buffer){
return ((buffer->in + 1) % buffer->size) == buffer->out;
}
bool ringbuffer_isempty(ringbuffer_t *buffer){
return buffer->in == buffer->out;
}
void ringbuffer_insert(ringbuffer_t *buffer, uint8_t val){
if(ringbuffer_isfull(buffer)) return;
buffer->buffer[buffer->in] = val;
if(++buffer->in == buffer->size) buffer->in = 0;
}
uint8_t ringbuffer_remove(ringbuffer_t *buffer){
uint8_t val = 0;
if(!ringbuffer_isempty(buffer)){
val = buffer->buffer[buffer->out];
if(++buffer->out == buffer->size) buffer->out = 0;
}
return val;
}
#ifndef _RINGBUFFER_H
#define _RINGBUFFER_H
#include <stm32f2xx.h>
#include <stdint.h>
#include <stdbool.h>
#include <rtl.h>
typedef struct {
uint8_t *buffer;
volatile uint16_t in;
volatile uint16_t out;
volatile uint16_t size;
} ringbuffer_t;
void ringbuffer_init(ringbuffer_t *buffer, uint16_t size);
void ringbuffer_deinit(ringbuffer_t *buffer);
bool ringbuffer_isfull(ringbuffer_t *buffer);
bool ringbuffer_isempty(ringbuffer_t *buffer);
void ringbuffer_insert(ringbuffer_t *buffer, uint8_t val);
uint8_t ringbuffer_remove(ringbuffer_t *buffer);
#endif
#include <stdlib.h>
#include <stm32f2xx.h>
#include "ringbuffer.h"
#include "serial.h"
serial_USART _serial_USART1 = {
.USART = USART1,
.GPIO = GPIOA,
.rxpin = GPIO_Pin_10,
.txpin = GPIO_Pin_9,
.rxpin_source = GPIO_PinSource10,
.txpin_source = GPIO_PinSource9,
.altfun = GPIO_AF_USART1,
.tx_buffer = NULL,
.rx_buffer = NULL,
};
serial_USART _serial_USART2 = {
.USART = USART2,
.GPIO = GPIOA,
.rxpin = GPIO_Pin_3,
.txpin = GPIO_Pin_2,
.rxpin_source = GPIO_PinSource3,
.txpin_source = GPIO_PinSource2,
.altfun = GPIO_AF_USART2,
};
serial_USART _serial_USART3 = {
.USART = USART3,
.GPIO = GPIOC,
.txpin = GPIO_Pin_10,
.rxpin = GPIO_Pin_11,
.txpin_source = GPIO_PinSource10,
.rxpin_source = GPIO_PinSource11,
.altfun GPIO_AF_USART3,
};
serial_USART *serial_USART1 = &_serial_USART1;
serial_USART *serial_USART2 = &_serial_USART2;
serial_USART *serial_USART3 = &_serial_USART3;
void serial_init(serial_USART *usart, int speed){
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
if(usart->tx_buffer != NULL || usart->rx_buffer != NULL)
return;
usart->tx_buffer = malloc(sizeof(*usart->tx_buffer));
usart->rx_buffer = malloc(sizeof(*usart->rx_buffer));
ringbuffer_init(usart->tx_buffer, 128);
ringbuffer_init(usart->rx_buffer, 128);
if(usart->USART == USART1)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
if(usart->USART == USART2)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
if(usart->USART == USART3)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
if(usart->GPIO == GPIOA)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
if(usart->GPIO == GPIOB)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
if(usart->GPIO == GPIOC)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
if(usart->GPIO == GPIOD)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_PinAFConfig(usart->GPIO, usart->txpin_source, usart->altfun);
GPIO_PinAFConfig(usart->GPIO, usart->rxpin_source, usart->altfun);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = usart->txpin;
GPIO_Init(usart->GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = usart->rxpin;
GPIO_Init(usart->GPIO, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = speed;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(usart->USART, &USART_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
if(usart->USART == USART1){
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
} else if(usart->USART == USART2){
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
} else if(usart->USART == USART3){
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
}
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_ITConfig(usart->USART, USART_IT_RXNE, ENABLE);
USART_Cmd(usart->USART, ENABLE);
}
signed int serial_getc(serial_USART *usart){
if(usart->rx_buffer == NULL) return -1;
if(ringbuffer_isempty(usart->rx_buffer)) return -1;
return (int)ringbuffer_remove(usart->rx_buffer);
}
bool serial_putc(serial_USART *usart, char c){
if(usart->tx_buffer == NULL) return false;
if(ringbuffer_isfull(usart->tx_buffer)) return false;
ringbuffer_insert(usart->tx_buffer, c);
USART_ITConfig(usart->USART, USART_IT_TXE, ENABLE);
return true;
}
void USART_IRQHandler(serial_USART *usart){
if(USART_GetITStatus(usart->USART, USART_IT_RXNE) != RESET){
uint8_t c;
c = USART_ReceiveData(usart->USART);
if(usart->rx_buffer == NULL) return;
if(!ringbuffer_isfull(usart->rx_buffer)){
ringbuffer_insert(usart->rx_buffer, c);
}
}
if(USART_GetITStatus(usart->USART, USART_IT_TXE)){
if(usart->tx_buffer == NULL){
USART_ITConfig(usart->USART, USART_IT_TXE, DISABLE);
} else if(ringbuffer_isempty(usart->tx_buffer)){
USART_ITConfig(usart->USART, USART_IT_TXE, DISABLE);
} else {
USART_SendData(usart->USART, ringbuffer_remove(usart->tx_buffer));
}
}
}
void USART1_IRQHandler(void){
USART_IRQHandler(serial_USART1);
}
void USART2_IRQHandler(void){
USART_IRQHandler(serial_USART2);
}
void USART3_IRQHandler(void){
USART_IRQHandler(serial_USART3);
}
#ifndef _SERIAL_H
#define _SERIAL_H
#include <stm32f2xx.h>
#include <stdint.h>
#include <stdbool.h>
#include "ringbuffer.h"
typedef struct {
USART_TypeDef *USART;
GPIO_TypeDef *GPIO;
uint16_t rxpin;
uint16_t txpin;
uint8_t rxpin_source;
uint8_t txpin_source;
uint8_t altfun;
ringbuffer_t *tx_buffer;
ringbuffer_t *rx_buffer;
} serial_USART;
extern serial_USART *serial_USART1;
extern serial_USART *serial_USART2;
extern serial_USART *serial_USART3;
void serial_init(serial_USART *usart, int speed);
bool serial_putc(serial_USART *usart, char c);
signed int serial_getc(serial_USART *usart);
#endif
@Do4Life
Copy link
Copy Markdown

Do4Life commented Sep 20, 2018

Hi DaveRichmond,
Please can you add comments on key sections of this code so that some of us new to UART programming can understand it better and can use it to make projects?
Best regards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment