Skip to content
This repository has been archived by the owner on Mar 14, 2024. It is now read-only.

Commit

Permalink
Updated uart architecture interface
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin Schröder committed Feb 15, 2015
1 parent e36202f commit 27b89ee
Show file tree
Hide file tree
Showing 22 changed files with 309 additions and 243 deletions.
8 changes: 8 additions & 0 deletions arch/arm/KConfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ choice
select HAVE_UART
select HAVE_UART0
select HAVE_UART1
select HAVE_UART2
select HAVE_TWI
select HAVE_TWI0
select HAVE_SPI
Expand All @@ -24,6 +25,13 @@ choice
select STM32
select HAVE_UART
select HAVE_UART0
select HAVE_UART1
select HAVE_UART2
select HAVE_TWI
select HAVE_TWI0
select HAVE_SPI
select HAVE_SPI0
select HAVE_SPI1
bool "STM32F100MDVL

config AT91SAM3
Expand Down
6 changes: 3 additions & 3 deletions arch/arm/stm32/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct spi_device {
int out_pins, in_pins, nss_pin;
};

static struct spi_device _spi[] = {
static const struct spi_device _spi[] = {
{
.spi = SPI1,
.gpio = GPIOA,
Expand Down Expand Up @@ -45,7 +45,7 @@ int16_t spi_init_device(uint8_t dev){

if(dev > count) return -1;

struct spi_device *d = &_spi[dev];
const struct spi_device *d = &_spi[dev];

RCC_APB2PeriphClockCmd ( d->rcc_gpio | RCC_APB2Periph_AFIO, ENABLE);

Expand Down Expand Up @@ -93,7 +93,7 @@ int16_t spi_init_device(uint8_t dev){
uint8_t spi_transfer(uint8_t dev, uint8_t data){
const uint8_t count = sizeof(_spi) / sizeof(_spi[0]);
if(dev > count) return 0xff;
struct spi_device *d = &_spi[dev];
const struct spi_device *d = &_spi[dev];

wait_on_us(SPI_I2S_GetFlagStatus(d->spi, SPI_I2S_FLAG_TXE) == RESET, SPI_TIMEOUT);

Expand Down
198 changes: 155 additions & 43 deletions arch/arm/stm32/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,79 @@

#include "uart.h"

#define UART_RX_BUFFER_SIZE 256
#define UART_RX_BUFFER_SIZE 64

struct uart_device {
USART_TypeDef *dev;
GPIO_TypeDef *gpio;
int rcc_gpio;
int rcc_id;
int apb_id;
int out_pins, in_pins;
int irq;
};

static const struct uart_device _devices[] = {
{
.dev = USART1,
.gpio = GPIOA,
.rcc_gpio = RCC_APB2Periph_GPIOA,
.rcc_id = RCC_APB2Periph_USART1,
.apb_id = 2,
.out_pins = GPIO_Pin_9,
.in_pins = GPIO_Pin_10,
.irq = USART1_IRQn
},
{
.dev = USART2,
.gpio = GPIOA,
.rcc_gpio = RCC_APB2Periph_GPIOA,
.rcc_id = RCC_APB1Periph_USART2,
.apb_id = 1,
.out_pins = GPIO_Pin_2,
.in_pins = GPIO_Pin_3,
.irq = USART2_IRQn
},
{
.dev = USART3,
.gpio = GPIOB,
.rcc_gpio = RCC_APB2Periph_GPIOB,
.rcc_id = RCC_APB1Periph_USART3,
.apb_id = 1,
.out_pins = GPIO_Pin_10,
.in_pins = GPIO_Pin_11,
.irq = USART3_IRQn
}
};

DECLARE_STATIC_CBUF(uart0_rx_buf, uint8_t, UART_RX_BUFFER_SIZE);
DECLARE_STATIC_CBUF(uart1_rx_buf, uint8_t, UART_RX_BUFFER_SIZE);
DECLARE_STATIC_CBUF(uart2_rx_buf, uint8_t, UART_RX_BUFFER_SIZE);
DECLARE_STATIC_CBUF(uart3_rx_buf, uint8_t, UART_RX_BUFFER_SIZE);
DECLARE_STATIC_CBUF(uart4_rx_buf, uint8_t, UART_RX_BUFFER_SIZE);
DECLARE_STATIC_CBUF(uart5_rx_buf, uint8_t, UART_RX_BUFFER_SIZE);

void uart0_init_default(uint32_t baud){
int8_t uart_init(uint8_t dev_id, uint32_t baud){
USART_InitTypeDef usartConfig;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 |
RCC_APB2Periph_GPIOA |
RCC_APB2Periph_AFIO, ENABLE);
USART_Cmd(USART1, ENABLE);

uint8_t count = sizeof(_devices) / sizeof(_devices[0]);

if(dev_id >= count) return -1;

const struct uart_device *conf = &_devices[dev_id];
USART_TypeDef *dev = _devices[dev_id].dev;

if(conf->apb_id == 2){
RCC_APB2PeriphClockCmd(conf->rcc_id, ENABLE);
} else if(conf->apb_id == 1){
RCC_APB1PeriphClockCmd(conf->rcc_id, ENABLE);
} else {
return -1;
}

RCC_APB2PeriphClockCmd(conf->rcc_gpio | RCC_APB2Periph_AFIO, ENABLE);

USART_Cmd(dev, ENABLE);

usartConfig.USART_BaudRate = baud;
usartConfig.USART_WordLength = USART_WordLength_8b;
Expand All @@ -50,49 +112,78 @@ void uart0_init_default(uint32_t baud){
usartConfig.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
usartConfig.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
USART_Init(USART1, &usartConfig);
USART_Init(dev, &usartConfig);

GPIO_InitTypeDef gpioConfig;

//PA9 = USART1.TX => Alternative Function Output
// configure tx pin
gpioConfig.GPIO_Mode = GPIO_Mode_AF_PP;
gpioConfig.GPIO_Pin = GPIO_Pin_9;
gpioConfig.GPIO_Pin = conf->out_pins;
gpioConfig.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &gpioConfig);
GPIO_Init(conf->gpio, &gpioConfig);

//PA10 = USART1.RX => Input
// configure rx pin
gpioConfig.GPIO_Mode = GPIO_Mode_IPU;
gpioConfig.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &gpioConfig);
gpioConfig.GPIO_Pin = conf->in_pins;
GPIO_Init(conf->gpio, &gpioConfig);

NVIC_InitTypeDef NVIC_InitStructure;

/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannel = conf->irq;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_ITConfig(dev, USART_IT_RXNE, ENABLE);

return 0;
}

uint16_t uart0_getc(void){
uint16_t uart_getc(uint8_t dev_id){
uint8_t count = sizeof(_devices) / sizeof(_devices[0]);
if(dev_id >= count) return SERIAL_NO_DATA;

USART_TypeDef *dev = _devices[dev_id].dev;

uint16_t ret = SERIAL_NO_DATA;
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
if(!cbuf_is_empty(&uart0_rx_buf)) {
ret = cbuf_get(&uart0_rx_buf);
USART_ITConfig(dev, USART_IT_RXNE, DISABLE);

// TODO: can probably be done better, but for now cbuf works this way..
switch(dev_id){
case 0:
if(!cbuf_is_empty(&uart0_rx_buf)) { ret = cbuf_get(&uart0_rx_buf); }
break;
case 1:
if(!cbuf_is_empty(&uart1_rx_buf)) { ret = cbuf_get(&uart1_rx_buf); }
break;
case 2:
if(!cbuf_is_empty(&uart2_rx_buf)) { ret = cbuf_get(&uart2_rx_buf); }
break;
case 3:
if(!cbuf_is_empty(&uart3_rx_buf)) { ret = cbuf_get(&uart3_rx_buf); }
break;
case 4:
if(!cbuf_is_empty(&uart4_rx_buf)) { ret = cbuf_get(&uart4_rx_buf); }
break;
case 5:
if(!cbuf_is_empty(&uart5_rx_buf)) { ret = cbuf_get(&uart5_rx_buf); }
break;
}
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_ITConfig(dev, USART_IT_RXNE, ENABLE);
return ret;
//if(!(USART1->SR & USART_SR_RXNE)) return SERIAL_NO_DATA;
//return USART1->DR & 0xff;
}

uint16_t uart0_putc(uint8_t ch){
while(!(USART1->SR & USART_SR_TXE));
USART1->DR = ch;
return 1;
int8_t uart_putc(uint8_t dev_id, uint8_t ch){
uint8_t count = sizeof(_devices) / sizeof(_devices[0]);
if(dev_id >= count) return -1;

USART_TypeDef *dev = _devices[dev_id].dev;

while(!(dev->SR & USART_SR_TXE));
dev->DR = ch;
return 0;
}

void USART1_IRQHandler(void);
Expand All @@ -106,25 +197,46 @@ void USART1_IRQHandler(void)
}
}

uint16_t uart0_waiting(void){
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
size_t cn = cbuf_get_data_count(&uart0_rx_buf);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
return cn;
//if(USART1->SR & USART_SR_RXNE) return 1;
//return 0;
}

void uart1_init_default(uint32_t baud){
(void)(baud);
void USART2_IRQHandler(void);
void USART2_IRQHandler(void)
{
if(USART2->SR & USART_FLAG_RXNE){
char ch = USART_ReceiveData(USART2);
if(!cbuf_is_full(&uart3_rx_buf)){
cbuf_put(&uart3_rx_buf, ch);
}
}
}

uint16_t uart1_getc(void){
return USART_ReceiveData(USART2);

void USART3_IRQHandler(void);
void USART3_IRQHandler(void)
{
if(USART3->SR & USART_FLAG_RXNE){
char ch = USART_ReceiveData(USART3);
if(!cbuf_is_full(&uart3_rx_buf)){
cbuf_put(&uart3_rx_buf, ch);
}
}
}

uint16_t uart1_putc(uint8_t ch){
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
USART_SendData(USART2, ch);
return 1;
uint16_t uart_waiting(uint8_t dev_id){
uint8_t count = sizeof(_devices) / sizeof(_devices[0]);
if(dev_id >= count) return -1;

USART_TypeDef *dev = _devices[dev_id].dev;
size_t cn = 0;

USART_ITConfig(dev, USART_IT_RXNE, DISABLE);
switch(dev_id){
case 0: cn = cbuf_get_data_count(&uart0_rx_buf); break;
case 1: cn = cbuf_get_data_count(&uart1_rx_buf); break;
case 2: cn = cbuf_get_data_count(&uart2_rx_buf); break;
case 3: cn = cbuf_get_data_count(&uart3_rx_buf); break;
case 4: cn = cbuf_get_data_count(&uart4_rx_buf); break;
case 5: cn = cbuf_get_data_count(&uart5_rx_buf); break;
}
USART_ITConfig(dev, USART_IT_RXNE, ENABLE);
return cn;
}
30 changes: 4 additions & 26 deletions arch/arm/stm32/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,7 @@

#pragma once

void uart0_init_default(uint32_t baud);
uint16_t uart0_getc(void);
uint16_t uart0_putc(uint8_t ch);
uint16_t uart0_waiting(void);

void uart1_init_default(uint32_t baud);
uint16_t uart1_getc(void);
uint16_t uart1_putc(uint8_t ch);
static inline int8_t uart1_waiting(void){
return 0;
}

/*
void uart0_init_default(uint16_t baudrate);
#define uart0_waiting() (USART_IsDataAvailable(USART0))
#define uart0_flush() do {} while(0)
#define uart0_getc() ((uart0_waiting())?USART_GetChar(USART0):UART_NO_DATA)
#define uart0_putc(data) (USART_PutChar(USART0, data), 0)
void uart1_init_default(uint16_t baud);
#define uart1_waiting() (USART_IsDataAvailable(USART1))
#define uart1_flush() do {} while(0)
#define uart1_getc() ((uart0_waiting())?USART_GetChar(USART1):UART_NO_DATA)
#define uart1_putc(data) (USART_PutChar(USART1, data), 0)
*/
int8_t uart_init(uint8_t dev_id, uint32_t baud);
uint16_t uart_getc(uint8_t dev_id);
int8_t uart_putc(uint8_t dev_id, uint8_t ch);
uint16_t uart_waiting(uint8_t dev_id);
2 changes: 1 addition & 1 deletion arch/arm/syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ int _read(int file, char *ptr, int len) {
switch (file) {
case STDIN_FILENO:
for (n = 0; n < len; n++) {
uint16_t c = uart0_getc();
uint16_t c = uart_getc(0);
if(c == SERIAL_NO_DATA) return -1;
*ptr++ = c;
num++;
Expand Down
30 changes: 29 additions & 1 deletion arch/avr/mega/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,33 @@
} while(timeout--);
return SERIAL_BUFFER_FULL;
}

#endif

int8_t uart_init(uint8_t dev_id, uint32_t baud){
switch(dev_id){
case 0: uart0_init_default(baud); break;
default: return -1;
}
return 0;
}

uint16_t uart_getc(uint8_t dev_id){
switch(dev_id){
case 0: return uart0_getc();
default: return SERIAL_NO_DATA;
}
}

int8_t uart_putc(uint8_t dev_id, uint8_t ch){
switch(dev_id){
case 0: uart0_putc(ch); return 0;
default: return -1;
}
}

uint16_t uart_waiting(uint8_t dev_id){
switch(dev_id){
case 0: return uart0_waiting();
default: return 0;
}
}
5 changes: 5 additions & 0 deletions arch/avr/mega/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ extern "C" {
#define uart0_putc(data) uart0_putc_direct(data)
#endif

int8_t uart_init(uint8_t dev_id, uint32_t baud);
uint16_t uart_getc(uint8_t dev_id);
int8_t uart_putc(uint8_t dev_id, uint8_t ch);
uint16_t uart_waiting(uint8_t dev_id);

#ifdef __cplusplus
}
#endif
Expand Down
Loading

0 comments on commit 27b89ee

Please sign in to comment.