From e3c19714d4ea0502dfd6b68d0c578ff7496d5c07 Mon Sep 17 00:00:00 2001 From: Ian Martin Date: Fri, 14 Mar 2014 16:06:24 -0400 Subject: [PATCH 1/4] cc2538: Support any UART baudrate. --- cpu/cc2538/dev/uart.c | 13 +++++++++-- cpu/cc2538/dev/uart.h | 51 +++++++++---------------------------------- 2 files changed, 21 insertions(+), 43 deletions(-) diff --git a/cpu/cc2538/dev/uart.c b/cpu/cc2538/dev/uart.c index 2354e565c..46b6c648a 100644 --- a/cpu/cc2538/dev/uart.c +++ b/cpu/cc2538/dev/uart.c @@ -92,7 +92,7 @@ reset(void) uint32_t lchr; /* Make sure the UART is disabled before trying to configure it */ - REG(UART_BASE | UART_CTL) = UART_CTL_TXE | UART_CTL_RXE; + REG(UART_BASE | UART_CTL) = UART_CTL_VALUE; /* Clear error status */ REG(UART_BASE | UART_ECR) = 0xFF; @@ -165,11 +165,20 @@ uart_init(void) UART_IFLS_RXIFLSEL_1_8 | UART_IFLS_TXIFLSEL_1_2; /* Make sure the UART is disabled before trying to configure it */ - REG(UART_BASE | UART_CTL) = UART_CTL_TXE | UART_CTL_RXE; + REG(UART_BASE | UART_CTL) = UART_CTL_VALUE; /* Baud Rate Generation */ +#if (defined UART_CONF_BAUD_RATE) + uart_set_baudrate(UART_CONF_BAUD_RATE); +#elif (defined UART_CONF_IBRD && defined UART_CONF_FBRD) REG(UART_BASE | UART_IBRD) = UART_CONF_IBRD; REG(UART_BASE | UART_FBRD) = UART_CONF_FBRD; +#else + #error "UART baud rate misconfigured and custom IBRD/FBRD values not provided" + #error "Check the value of UART_CONF_BAUD_RATE in contiki-conf.h or project-conf.h" + #error "Alternatively, you can provide custom values for " + #error "UART_CONF_IBRD and UART_CONF_FBRD" +#endif /* UART Control: 8N1 with FIFOs */ REG(UART_BASE | UART_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN; diff --git a/cpu/cc2538/dev/uart.h b/cpu/cc2538/dev/uart.h index 8ae5dc486..37919188a 100644 --- a/cpu/cc2538/dev/uart.h +++ b/cpu/cc2538/dev/uart.h @@ -65,50 +65,19 @@ * \name Baud rate defines * * Used in uart_init() to set the values of UART_IBRD and UART_FBRD in order to - * achieve some standard baud rates. These defines assume that the UART is - * clocked at 16MHz and that Clock Div is 16 (UART_CTL:HSE clear) + * achieve some standard baud rates. * @{ */ -#define UART_IBRD_9600 104 /**< IBRD value for baud rate 9600 */ -#define UART_FBRD_9600 11 /**< FBRD value for baud rate 9600 */ -#define UART_IBRD_38400 26 /**< IBRD value for baud rate 38400 */ -#define UART_FBRD_38400 3 /**< FBRD value for baud rate 38400 */ -#define UART_IBRD_57600 17 /**< IBRD value for baud rate 57600 */ -#define UART_FBRD_57600 24 /**< FBRD value for baud rate 57600 */ -#define UART_IBRD_115200 8 /**< IBRD value for baud rate 115200 */ -#define UART_FBRD_115200 44 /**< FBRD value for baud rate 115200 */ -#define UART_IBRD_230400 4 /**< IBRD value for baud rate 230400 */ -#define UART_FBRD_230400 22 /**< FBRD value for baud rate 230400 */ -#define UART_IBRD_460800 2 /**< IBRD value for baud rate 460800 */ -#define UART_FBRD_460800 11 /**< FBRD value for baud rate 460800 */ +#define UART_CLOCK_RATE 16000000 /* 16 MHz */ +#define UART_CTL_HSE_VALUE 0 +#define UART_CTL_VALUE ( UART_CTL_RXE | UART_CTL_TXE | (UART_CTL_HSE_VALUE << 5) ) +#define BAUD2BRD(baud) ( (UART_CLOCK_RATE << (UART_CTL_HSE_VALUE + 2)) / (baud) ) + +#define uart_set_baudrate(baud) ( \ + REG(UART_BASE | UART_IBRD) = BAUD2BRD(baud) >> 6, \ + REG(UART_BASE | UART_FBRD) = BAUD2BRD(baud) & 0x3f, \ + REG(UART_BASE | UART_LCRH) = REG(UART_BASE | UART_LCRH) ) -#if UART_CONF_BAUD_RATE==9600 -#define UART_CONF_IBRD UART_IBRD_9600 -#define UART_CONF_FBRD UART_FBRD_9600 -#elif UART_CONF_BAUD_RATE==38400 -#define UART_CONF_IBRD UART_IBRD_38400 -#define UART_CONF_FBRD UART_FBRD_38400 -#elif UART_CONF_BAUD_RATE==57600 -#define UART_CONF_IBRD UART_IBRD_57600 -#define UART_CONF_FBRD UART_FBRD_57600 -#elif UART_CONF_BAUD_RATE==115200 -#define UART_CONF_IBRD UART_IBRD_115200 -#define UART_CONF_FBRD UART_FBRD_115200 -#elif UART_CONF_BAUD_RATE==230400 -#define UART_CONF_IBRD UART_IBRD_230400 -#define UART_CONF_FBRD UART_FBRD_230400 -#elif UART_CONF_BAUD_RATE==460800 -#define UART_CONF_IBRD UART_IBRD_460800 -#define UART_CONF_FBRD UART_FBRD_460800 -#else /* Bail out with an error unless the user provided custom values */ -#if !(defined UART_CONF_IBRD && defined UART_CONF_FBRD) -#error "UART baud rate misconfigured and custom IBRD/FBRD values not provided" -#error "Check the value of UART_CONF_BAUD_RATE in contiki-conf.h or project-conf.h" -#error "Supported values are 9600, 38400, 57600, 115200, 230400 and 460800." -#error "Alternatively, you can provide custom values for " -#error "UART_CONF_IBRD and UART_CONF_FBRD" -#endif -#endif /** @} */ /*---------------------------------------------------------------------------*/ /** \name UART Register Offsets From 1ceb8ae3583524ed731886f07f617e27d6edda43 Mon Sep 17 00:00:00 2001 From: Ian Martin Date: Sat, 22 Mar 2014 10:21:54 -0400 Subject: [PATCH 2/4] Fix rounding error in baudrate calculation. --- cpu/cc2538/dev/uart.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cpu/cc2538/dev/uart.h b/cpu/cc2538/dev/uart.h index 37919188a..8e9d79f3d 100644 --- a/cpu/cc2538/dev/uart.h +++ b/cpu/cc2538/dev/uart.h @@ -71,7 +71,11 @@ #define UART_CLOCK_RATE 16000000 /* 16 MHz */ #define UART_CTL_HSE_VALUE 0 #define UART_CTL_VALUE ( UART_CTL_RXE | UART_CTL_TXE | (UART_CTL_HSE_VALUE << 5) ) -#define BAUD2BRD(baud) ( (UART_CLOCK_RATE << (UART_CTL_HSE_VALUE + 2)) / (baud) ) + +/* DIV_ROUND() divides integers while avoiding a rounding error: */ +#define DIV_ROUND(num, denom) ( ((num) + (denom) / 2) / (denom) ) + +#define BAUD2BRD(baud) DIV_ROUND(UART_CLOCK_RATE << (UART_CTL_HSE_VALUE + 2), (baud)) #define uart_set_baudrate(baud) ( \ REG(UART_BASE | UART_IBRD) = BAUD2BRD(baud) >> 6, \ From ee45fc7533d97904edc5698a79f1159c24c5e7f2 Mon Sep 17 00:00:00 2001 From: Ian Martin Date: Sat, 22 Mar 2014 10:22:11 -0400 Subject: [PATCH 3/4] Change uart_set_baudrate() to a do-while statement. --- cpu/cc2538/dev/uart.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cpu/cc2538/dev/uart.h b/cpu/cc2538/dev/uart.h index 8e9d79f3d..fbc18fc18 100644 --- a/cpu/cc2538/dev/uart.h +++ b/cpu/cc2538/dev/uart.h @@ -77,10 +77,11 @@ #define BAUD2BRD(baud) DIV_ROUND(UART_CLOCK_RATE << (UART_CTL_HSE_VALUE + 2), (baud)) -#define uart_set_baudrate(baud) ( \ - REG(UART_BASE | UART_IBRD) = BAUD2BRD(baud) >> 6, \ - REG(UART_BASE | UART_FBRD) = BAUD2BRD(baud) & 0x3f, \ - REG(UART_BASE | UART_LCRH) = REG(UART_BASE | UART_LCRH) ) +#define uart_set_baudrate(baud) do { \ + REG(UART_BASE | UART_IBRD) = BAUD2BRD(baud) >> 6; \ + REG(UART_BASE | UART_FBRD) = BAUD2BRD(baud) & 0x3f; \ + REG(UART_BASE | UART_LCRH) = REG(UART_BASE | UART_LCRH); \ +} while(0) /** @} */ /*---------------------------------------------------------------------------*/ From 336224633ac3961026a55723c18279f6e5f18583 Mon Sep 17 00:00:00 2001 From: Ian Martin Date: Sat, 22 Mar 2014 10:26:03 -0400 Subject: [PATCH 4/4] Eliminate UART_CONF_IBRD and UART_CONF_FBRD. --- cpu/cc2538/dev/uart.c | 10 ---------- platform/cc2538dk/README.md | 8 -------- 2 files changed, 18 deletions(-) diff --git a/cpu/cc2538/dev/uart.c b/cpu/cc2538/dev/uart.c index 46b6c648a..1ab2f81f1 100644 --- a/cpu/cc2538/dev/uart.c +++ b/cpu/cc2538/dev/uart.c @@ -168,17 +168,7 @@ uart_init(void) REG(UART_BASE | UART_CTL) = UART_CTL_VALUE; /* Baud Rate Generation */ -#if (defined UART_CONF_BAUD_RATE) uart_set_baudrate(UART_CONF_BAUD_RATE); -#elif (defined UART_CONF_IBRD && defined UART_CONF_FBRD) - REG(UART_BASE | UART_IBRD) = UART_CONF_IBRD; - REG(UART_BASE | UART_FBRD) = UART_CONF_FBRD; -#else - #error "UART baud rate misconfigured and custom IBRD/FBRD values not provided" - #error "Check the value of UART_CONF_BAUD_RATE in contiki-conf.h or project-conf.h" - #error "Alternatively, you can provide custom values for " - #error "UART_CONF_IBRD and UART_CONF_FBRD" -#endif /* UART Control: 8N1 with FIFOs */ REG(UART_BASE | UART_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN; diff --git a/platform/cc2538dk/README.md b/platform/cc2538dk/README.md index 04941fddd..0a04d6b9a 100644 --- a/platform/cc2538dk/README.md +++ b/platform/cc2538dk/README.md @@ -367,14 +367,6 @@ By default, the CC2538 UART is configured with a baud rate of 115200. It is easy #define UART_CONF_BAUD_RATE 230400 -Currently, this configuration directive only supports values 115200, 230400 and 460800. Custom baud rates can also be achieved by following the steps below: - -* Configure `UART_CONF_BAUD_RATE` with an unsupported value to prevent it from auto-choosing values for IBRD and FBRD. For instance, in your project-conf.h you can do: - - #define UART_CONF_BAUD_RATE 0 - -* Provide custom values for `UART_CONF_IBRD` and `UART_CONF_FBRD` according to the guidelines in the CC2538 User Guide. - RF and USB DMA -------------- Transfers between RAM and the RF and USB will be conducted with DMA. If for whatever reason you wish to disable this, here are the relevant configuration lines.