Created
December 1, 2012 07:20
-
-
Save DaveRichmond/4180948 to your computer and use it in GitHub Desktop.
STM32F2 USART
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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); | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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); | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.