diff --git a/boards/arduino-due/Makefile.features b/boards/arduino-due/Makefile.features index 9be17cbb4b..4f578052e2 100644 --- a/boards/arduino-due/Makefile.features +++ b/boards/arduino-due/Makefile.features @@ -1 +1 @@ -FEATURES_PROVIDED += periph_gpio periph_spi periph_random +FEATURES_PROVIDED += periph_uart periph_gpio periph_spi periph_random diff --git a/boards/arduino-due/include/board.h b/boards/arduino-due/include/board.h index 8344da85c1..f63fcda1d3 100644 --- a/boards/arduino-due/include/board.h +++ b/boards/arduino-due/include/board.h @@ -43,6 +43,7 @@ extern "C" { */ #define STDIO UART_0 #define STDIO_BAUDRATE (115200U) +#define STDIO_RX_BUFSIZE (64U) /** @} */ /** diff --git a/boards/arduino-due/include/periph_conf.h b/boards/arduino-due/include/periph_conf.h index 4a27af3edb..464ca4702e 100644 --- a/boards/arduino-due/include/periph_conf.h +++ b/boards/arduino-due/include/periph_conf.h @@ -59,15 +59,17 @@ extern "C" { * @name UART configuration * @{ */ -#define UART_NUMOF (1U) +#define UART_NUMOF (4U) #define UART_0_EN 1 -#define UART_1_EN 0 -#define UART_2_EN 0 -#define UART_3_EN 0 +#define UART_1_EN 1 +#define UART_2_EN 1 +#define UART_3_EN 1 #define UART_IRQ_PRIO 1 /* UART 0 device configuration */ #define UART_0_DEV UART +#define UART_0_CLKEN() (PMC->PMC_PCER0 |= (1 << ID_UART)) +#define UART_0_CLKDIS() (PMC->PMC_PCER0 &= ~(1 << ID_UART)) #define UART_0_IRQ UART_IRQn #define UART_0_ISR isr_uart /* UART 0 pin configuration */ @@ -75,12 +77,34 @@ extern "C" { #define UART_0_PINS (PIO_PA8 | PIO_PA9) /* UART 1 device configuration */ -#define UART_1_DEV -#define UART_1_IRQ -#define UART_1_ISR +#define UART_1_DEV USART0 +#define UART_1_CLKEN() (PMC->PMC_PCER0 |= (1 << ID_USART0)) +#define UART_1_CLKDIS() (PMC->PMC_PCER0 &= ~(1 << ID_USART0)) +#define UART_1_IRQ USART0_IRQn +#define UART_1_ISR isr_usart0 /* UART 1 pin configuration */ -#define UART_1_PORT -#define UART_1_PINS +#define UART_1_PORT PIOA +#define UART_1_PINS (PIO_PA10 | PIO_PA11) + +/* UART 1 device configuration */ +#define UART_2_DEV USART1 +#define UART_2_CLKEN() (PMC->PMC_PCER0 |= (1 << ID_USART1)) +#define UART_2_CLKDIS() (PMC->PMC_PCER0 &= ~(1 << ID_USART1)) +#define UART_2_IRQ USART1_IRQn +#define UART_2_ISR isr_usart1 +/* UART 1 pin configuration */ +#define UART_2_PORT PIOA +#define UART_2_PINS (PIO_PA12 | PIO_PA13) + +/* UART 1 device configuration */ +#define UART_3_DEV USART3 +#define UART_3_CLKEN() (PMC->PMC_PCER0 |= (1 << ID_USART3)) +#define UART_3_CLKDIS() (PMC->PMC_PCER0 &= ~(1 << ID_USART3)) +#define UART_3_IRQ USART3_IRQn +#define UART_3_ISR isr_usart3 +/* UART 1 pin configuration */ +#define UART_3_PORT PIOD +#define UART_3_PINS (PIO_PD4 | PIO_PD5) /** @} */ /** diff --git a/boards/udoo/Makefile.features b/boards/udoo/Makefile.features index 9be17cbb4b..4f578052e2 100644 --- a/boards/udoo/Makefile.features +++ b/boards/udoo/Makefile.features @@ -1 +1 @@ -FEATURES_PROVIDED += periph_gpio periph_spi periph_random +FEATURES_PROVIDED += periph_uart periph_gpio periph_spi periph_random diff --git a/boards/udoo/include/board.h b/boards/udoo/include/board.h index 262f4af1b8..96c8a14af9 100644 --- a/boards/udoo/include/board.h +++ b/boards/udoo/include/board.h @@ -44,6 +44,7 @@ extern "C" { */ #define STDIO UART_0 #define STDIO_BAUDRATE (115200U) +#define STDIO_RX_BUFSIZE (64U) /** @} */ /** diff --git a/boards/udoo/include/periph_conf.h b/boards/udoo/include/periph_conf.h index 5d4be8511e..c6e87101e4 100644 --- a/boards/udoo/include/periph_conf.h +++ b/boards/udoo/include/periph_conf.h @@ -58,15 +58,17 @@ extern "C" { * @name UART configuration * @{ */ -#define UART_NUMOF (1U) +#define UART_NUMOF (4U) #define UART_0_EN 1 -#define UART_1_EN 0 -#define UART_2_EN 0 -#define UART_3_EN 0 +#define UART_1_EN 1 +#define UART_2_EN 1 +#define UART_3_EN 1 #define UART_IRQ_PRIO 1 /* UART 0 device configuration */ #define UART_0_DEV UART +#define UART_0_CLKEN() (PMC->PMC_PCER0 |= (1 << ID_UART)) +#define UART_0_CLKDIS() (PMC->PMC_PCER0 &= ~(1 << ID_UART)) #define UART_0_IRQ UART_IRQn #define UART_0_ISR isr_uart /* UART 0 pin configuration */ @@ -74,12 +76,34 @@ extern "C" { #define UART_0_PINS (PIO_PA8 | PIO_PA9) /* UART 1 device configuration */ -#define UART_1_DEV USART2 -#define UART_1_IRQ USART2_IRQn -#define UART_1_ISR isr_usart2 +#define UART_1_DEV USART0 +#define UART_1_CLKEN() (PMC->PMC_PCER0 |= (1 << ID_USART0)) +#define UART_1_CLKDIS() (PMC->PMC_PCER0 &= ~(1 << ID_USART0)) +#define UART_1_IRQ USART0_IRQn +#define UART_1_ISR isr_usart0 /* UART 1 pin configuration */ -#define UART_1_PORT GPIOA -#define UART_1_PINS (GPIO_Pin_2 | GPIO_Pin_3) +#define UART_1_PORT PIOA +#define UART_1_PINS (PIO_PA10 | PIO_PA11) + +/* UART 1 device configuration */ +#define UART_2_DEV USART1 +#define UART_2_CLKEN() (PMC->PMC_PCER0 |= (1 << ID_USART1)) +#define UART_2_CLKDIS() (PMC->PMC_PCER0 &= ~(1 << ID_USART1)) +#define UART_2_IRQ USART1_IRQn +#define UART_2_ISR isr_usart1 +/* UART 1 pin configuration */ +#define UART_2_PORT PIOA +#define UART_2_PINS (PIO_PA12 | PIO_PA13) + +/* UART 1 device configuration */ +#define UART_3_DEV USART3 +#define UART_3_CLKEN() (PMC->PMC_PCER0 |= (1 << ID_USART3)) +#define UART_3_CLKDIS() (PMC->PMC_PCER0 &= ~(1 << ID_USART3)) +#define UART_3_IRQ USART3_IRQn +#define UART_3_ISR isr_usart3 +/* UART 1 pin configuration */ +#define UART_3_PORT PIOD +#define UART_3_PINS (PIO_PD4 | PIO_PD5) /** @} */ /** diff --git a/cpu/sam3x8e/Makefile.include b/cpu/sam3x8e/Makefile.include index 8c3e53c46a..c2467ca40a 100644 --- a/cpu/sam3x8e/Makefile.include +++ b/cpu/sam3x8e/Makefile.include @@ -1,13 +1,21 @@ - # this CPU implementation is using the new core/CPU interface export CFLAGS += -DCOREIF_NG=1 +# export the peripheral drivers to be linked into the final binary +export USEMODULE += periph + +# this CPU implementation makes use of the ringbuffer, so include the lib module +export USEMODULE += lib + # tell the build system that the CPU depends on the Cortex-M common files export USEMODULE += cortex-m3_common # define path to cortex-m common module, which is needed for this CPU export CORTEX_COMMON = $(RIOTCPU)/cortex-m3_common/ +# CPU depends on the cortex-m common module, so include it +include $(CORTEX_COMMON)Makefile.include + # define the linker script to use for this CPU export LINKERSCRIPT ?= $(RIOTCPU)/$(CPU)/sam3x8e_linkerscript.ld @@ -18,9 +26,3 @@ export INCLUDES += -I$(RIOTCPU)/$(CPU)/include # Without this the interrupt vectors will not be linked correctly! export UNDEF += $(BINDIR)cpu/syscalls.o export UNDEF += $(BINDIR)cpu/startup.o - -# export the peripheral drivers to be linked into the final binary -export USEMODULE += periph - -# CPU depends on the cortex-m common module, so include it -include $(CORTEX_COMMON)Makefile.include diff --git a/cpu/sam3x8e/periph/uart.c b/cpu/sam3x8e/periph/uart.c index 886ba7bda8..f20a791576 100644 --- a/cpu/sam3x8e/periph/uart.c +++ b/cpu/sam3x8e/periph/uart.c @@ -20,10 +20,14 @@ #include "board.h" #include "cpu.h" - +#include "sched.h" +#include "thread.h" #include "periph/uart.h" #include "periph_conf.h" +#define ENABLE_DEBUG (0) +#include "debug.h" + /* guard file in case no UART device was specified */ #if UART_NUMOF @@ -57,9 +61,34 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, uart_tx_cb_t t /* configure interrupts and enable RX interrupt */ switch (uart) { +#if UART_0_EN case UART_0: + NVIC_SetPriority(UART_0_IRQ, UART_IRQ_PRIO); + NVIC_EnableIRQ(UART_0_IRQ); UART_0_DEV->UART_IER = UART_IER_RXRDY; - break; + break; +#endif +#if UART_1_EN + case UART_1: + NVIC_SetPriority(UART_1_IRQ, UART_IRQ_PRIO); + NVIC_EnableIRQ(UART_1_IRQ); + UART_1_DEV->US_IER = US_IER_RXRDY; + break; +#endif +#if UART_2_EN + case UART_2: + NVIC_SetPriority(UART_2_IRQ, UART_IRQ_PRIO); + NVIC_EnableIRQ(UART_2_IRQ); + UART_2_DEV->US_IER = US_IER_RXRDY; + break; +#endif +#if UART_3_EN + case UART_3: + NVIC_SetPriority(UART_3_IRQ, UART_IRQ_PRIO); + NVIC_EnableIRQ(UART_3_IRQ); + UART_3_DEV->US_IER = US_IER_RXRDY; + break; +#endif } return 0; } @@ -67,12 +96,16 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, uart_tx_cb_t t int uart_init_blocking(uart_t uart, uint32_t baudrate) { uint16_t clock_divider = F_CPU / (16 * baudrate); + switch (uart) { #if UART_0_EN case UART_0: + /* enable uart clock */ + UART_0_CLKEN(); + /* configure PINS */ UART_0_PORT->PIO_PDR = UART_0_PINS; - UART_0_PORT->PIO_ABSR &= ~UART_0_PINS; + UART_0_PORT->PIO_ABSR &= ~UART_0_PINS; /* periph function A */ /* set clock divider */ UART_0_DEV->UART_BRGR = clock_divider; @@ -81,6 +114,57 @@ int uart_init_blocking(uart_t uart, uint32_t baudrate) /* enable receiver and transmitter and reset status bits */ UART_0_DEV->UART_CR = UART_CR_RXEN | UART_CR_TXEN | UART_CR_RSTSTA; break; +#endif +#if UART_1_EN + case UART_1: + /* enable uart clock */ + UART_1_CLKEN(); + + /* configure PINS */ + UART_1_PORT->PIO_PDR = UART_1_PINS; + UART_1_PORT->PIO_ABSR &= ~UART_1_PINS; /* periph function A */ + + /* set clock divider */ + UART_1_DEV->US_BRGR = clock_divider; + /* set to normal mode without parity */ + UART_1_DEV->US_MR = US_MR_CHRL_8_BIT | US_MR_PAR_NO; + /* enable receiver and transmitter and reset status bits */ + UART_1_DEV->US_CR = US_CR_RXEN | US_CR_TXEN | US_CR_RSTSTA; + break; +#endif +#if UART_2_EN + case UART_2: + /* enable uart clock */ + UART_2_CLKEN(); + + /* configure PINS */ + UART_2_PORT->PIO_PDR = UART_2_PINS; + UART_2_PORT->PIO_ABSR &= ~UART_2_PINS; /* periph function A */ + + /* set clock divider */ + UART_2_DEV->US_BRGR = clock_divider; + /* set to normal mode without parity */ + UART_2_DEV->US_MR = US_MR_CHRL_8_BIT | US_MR_PAR_NO; + /* enable receiver and transmitter and reset status bits */ + UART_2_DEV->US_CR = US_CR_RXEN | US_CR_TXEN | US_CR_RSTSTA; + break; +#endif +#if UART_3_EN + case UART_3: + /* enable uart clock */ + UART_3_CLKEN(); + + /* configure PINS */ + UART_3_PORT->PIO_PDR = UART_3_PINS; + UART_3_PORT->PIO_ABSR |= UART_3_PINS; /* periph function B */ + + /* set clock divider */ + UART_3_DEV->US_BRGR = clock_divider; + /* set to normal mode without parity */ + UART_3_DEV->US_MR = US_MR_CHRL_8_BIT | US_MR_PAR_NO; + /* enable receiver and transmitter and reset status bits */ + UART_3_DEV->US_CR = US_CR_RXEN | US_CR_TXEN | US_CR_RSTSTA; + break; #endif } return 0; @@ -88,20 +172,53 @@ int uart_init_blocking(uart_t uart, uint32_t baudrate) void uart_tx_begin(uart_t uart) { - -} - -void uart_tx_end(uart_t uart) -{ - + switch (uart) { +#if UART_0_EN + case UART_0: + UART_0_DEV->UART_IER = UART_IER_TXRDY; + break; +#endif +#if UART_1_EN + case UART_1: + UART_1_DEV->US_IER = US_IER_TXRDY; + break; +#endif +#if UART_2_EN + case UART_2: + UART_2_DEV->US_IER = US_IER_TXRDY; + break; +#endif +#if UART_3_EN + case UART_3: + UART_3_DEV->US_IER = US_IER_TXRDY; + break; +#endif + } } int uart_write(uart_t uart, char data) { switch (uart) { +#if UART_0_EN case UART_0: UART_0_DEV->UART_THR = data; break; +#endif +#if UART_1_EN + case UART_1: + UART_1_DEV->US_THR = data; + break; +#endif +#if UART_2_EN + case UART_2: + UART_2_DEV->US_THR = data; + break; +#endif +#if UART_3_EN + case UART_3: + UART_3_DEV->US_THR = data; + break; +#endif } return 1; } @@ -109,33 +226,188 @@ int uart_write(uart_t uart, char data) int uart_read_blocking(uart_t uart, char *data) { switch (uart) { +#if UART_0_EN case UART_0: while (!(UART_0_DEV->UART_SR & UART_SR_RXRDY)); *data = (char)UART_0_DEV->UART_RHR; break; +#endif +#if UART_1_EN + case UART_1: + while (!(UART_1_DEV->US_CSR & US_CSR_RXRDY)); + *data = (char)UART_1_DEV->US_RHR; + break; +#endif +#if UART_2_EN + case UART_2: + while (!(UART_2_DEV->US_CSR & US_CSR_RXRDY)); + *data = (char)UART_2_DEV->US_RHR; + break; +#endif +#if UART_3_EN + case UART_3: + while (!(UART_3_DEV->US_CSR & US_CSR_RXRDY)); + *data = (char)UART_3_DEV->US_RHR; + break; +#endif } + return 1; } int uart_write_blocking(uart_t uart, char data) { switch (uart) { +#if UART_0_EN case UART_0: while (!(UART_0_DEV->UART_SR & UART_SR_TXRDY)); UART_0_DEV->UART_THR = data; break; +#endif +#if UART_1_EN + case UART_1: + while(!(UART_1_DEV->US_CSR & US_CSR_TXRDY)); + UART_1_DEV->US_THR = data; + break; +#endif +#if UART_2_EN + case UART_2: + while(!(UART_2_DEV->US_CSR & US_CSR_TXRDY)); + UART_2_DEV->US_THR = data; + break; +#endif +#if UART_3_EN + case UART_3: + while(!(UART_3_DEV->US_CSR & US_CSR_TXRDY)); + UART_3_DEV->US_THR = data; + break; +#endif } return 1; } void uart_poweron(uart_t uart) { - + switch (uart) { +#if UART_0_EN + case UART_0: + UART_0_CLKEN(); + break; +#endif +#if UART_1_EN + case UART_1: + UART_1_CLKEN(); + break; +#endif +#if UART_2_EN + case UART_2: + UART_2_CLKEN(); + break; +#endif +#if UART_3_EN + case UART_3: + UART_3_CLKEN(); + break; +#endif + } } void uart_poweroff(uart_t uart) { - + switch (uart) { +#if UART_0_EN + case UART_0: + UART_0_CLKDIS(); + break; +#endif +#if UART_1_EN + case UART_1: + UART_1_CLKDIS(); + break; +#endif +#if UART_2_EN + case UART_2: + UART_2_CLKDIS(); + break; +#endif +#if UART_3_EN + case UART_3: + UART_3_CLKDIS(); + break; +#endif + } } +#if UART_0_EN +void UART_0_ISR(void) +{ + if (UART_0_DEV->UART_SR & UART_SR_RXRDY) { + char data = (char)UART_0_DEV->UART_RHR; + uart_config[UART_0].rx_cb(uart_config[UART_0].arg, data); + } + if ((UART_0_DEV->UART_SR & UART_SR_TXRDY) && (UART_0_DEV->UART_IMR & UART_IMR_TXRDY)) { + if (uart_config[UART_0].tx_cb(uart_config[UART_0].arg) == 0) { + UART_0_DEV->UART_IDR = UART_IDR_TXRDY; + } + } + if (sched_context_switch_request) { + thread_yield(); + } +} +#endif + +#if UART_1_EN +void UART_1_ISR(void) +{ + if (UART_1_DEV->US_CSR & US_CSR_RXRDY) { + char data = (char)UART_1_DEV->US_RHR; + uart_config[UART_1].rx_cb(uart_config[UART_1].arg, data); + } + if ((UART_1_DEV->US_CSR & US_CSR_TXRDY) && (UART_1_DEV->US_IMR & US_IMR_TXRDY)) { + if (uart_config[UART_1].tx_cb(uart_config[UART_1].arg) == 0) { + UART_1_DEV->US_IDR = US_IDR_TXRDY; + } + } + if (sched_context_switch_request) { + thread_yield(); + } +} +#endif + +#if UART_2_EN +void UART_2_ISR(void) +{ + if (UART_2_DEV->US_CSR & US_CSR_RXRDY) { + char data = (char)UART_2_DEV->US_RHR; + uart_config[UART_2].rx_cb(uart_config[UART_2].arg, data); + } + if ((UART_2_DEV->US_CSR & US_CSR_TXRDY) && (UART_2_DEV->US_IMR & US_IMR_TXRDY)) { + if (uart_config[UART_2].tx_cb(uart_config[UART_2].arg) == 0) { + UART_2_DEV->US_IDR = US_IDR_TXRDY; + } + } + if (sched_context_switch_request) { + thread_yield(); + } +} +#endif + +#if UART_3_EN +void UART_3_ISR(void) +{ + if (UART_3_DEV->US_CSR & US_CSR_RXRDY) { + char data = (char)UART_3_DEV->US_RHR; + uart_config[UART_3].rx_cb(uart_config[UART_3].arg, data); + } + if ((UART_3_DEV->US_CSR & US_CSR_TXRDY) && (UART_3_DEV->US_IMR & US_IMR_TXRDY)) { + if (uart_config[UART_3].tx_cb(uart_config[UART_3].arg) == 0) { + UART_3_DEV->US_IDR = US_IDR_TXRDY; + } + } + if (sched_context_switch_request) { + thread_yield(); + } +} +#endif + #endif /* UART_NUMOF */ diff --git a/cpu/sam3x8e/syscalls.c b/cpu/sam3x8e/syscalls.c index 0b5aacdecf..f060896592 100644 --- a/cpu/sam3x8e/syscalls.c +++ b/cpu/sam3x8e/syscalls.c @@ -31,21 +31,60 @@ #include "board.h" #include "thread.h" #include "kernel.h" +#include "mutex.h" +#include "ringbuffer.h" #include "irq.h" #include "periph/uart.h" +#ifdef MODULE_UART0 +#include "board_uart0.h" +#endif + /** * manage the heap */ extern char _sheap; /* start of the heap */ extern char _eheap; /* end of the heap */ caddr_t heap_top = (caddr_t)&_sheap + 4; + +#ifndef MODULE_UART0 +/** + * @brief use mutex for waiting on incoming UART chars + */ +static mutex_t uart_rx_mutex; +static char rx_buf_mem[STDIO_RX_BUFSIZE]; +static ringbuffer_t rx_buf; +#endif + +/** + * @brief Receive a new character from the UART and put it into the receive buffer + */ +void rx_cb(void *arg, char data) +{ +#ifndef MODULE_UART0 + (void)arg; + + ringbuffer_add_one(&rx_buf, data); + mutex_unlock(&uart_rx_mutex); +#else + if (uart0_handler_pid) { + uart0_handle_incoming(data); + + uart0_notify_thread(); + } +#endif +} + /** * @brief Initialize NewLib, called by __libc_init_array() from the startup script */ void _init(void) { - uart_init_blocking(STDIO, STDIO_BAUDRATE); +#ifndef MODULE_UART0 + mutex_init(&uart_rx_mutex); + ringbuffer_init(&rx_buf, rx_buf_mem, STDIO_RX_BUFSIZE); +#endif + uart_init(STDIO, STDIO_BAUDRATE, rx_cb, 0, 0); } /** @@ -157,11 +196,16 @@ int _open_r(struct _reent *r, const char *name, int mode) */ int _read_r(struct _reent *r, int fd, void *buffer, unsigned int count) { - char c; - char *buff = (char*)buffer; - uart_read_blocking(UART_0, &c); - buff[0] = c; +#ifndef MODULE_UART0 + while (rx_buf.avail == 0) { + mutex_lock(&uart_rx_mutex); + } + return ringbuffer_get(&rx_buf, (char*)buffer, rx_buf.avail); +#else + char *res = (char*)buffer; + res[0] = (char)uart0_readc(); return 1; +#endif } /** @@ -181,9 +225,8 @@ int _read_r(struct _reent *r, int fd, void *buffer, unsigned int count) */ int _write_r(struct _reent *r, int fd, const void *data, unsigned int count) { - char *c = (char*)data; for (int i = 0; i < count; i++) { - uart_write_blocking(UART_0, c[i]); + uart_write_blocking(UART_0, ((char *)data)[i]); } return count; }