diff --git a/contrib/usart-stm32.c b/contrib/usart-stm32.c index d8d28fa..a7b72f5 100644 --- a/contrib/usart-stm32.c +++ b/contrib/usart-stm32.c @@ -57,7 +57,21 @@ static struct USART *const USART3 = (struct SYSCFG *)USART3_BASE; #define USART_SR_FE (1 << 1) #define USART_SR_PE (1 << 0) -#define USART_CR1_TXEIE (1 << 7) + +#define USART_CR1_UE (1 << 13) +#define USART_CR1_M (1 << 12) +#define USART_CR1_WAKE (1 << 11) +#define USART_CR1_PCE (1 << 10) +#define USART_CR1_PS (1 << 9) +#define USART_CR1_PEIE (1 << 8) +#define USART_CR1_TXEIE (1 << 7) +#define USART_CR1_TCIE (1 << 6) +#define USART_CR1_RXNEIE (1 << 5) +#define USART_CR1_IDLEIE (1 << 4) +#define USART_CR1_TE (1 << 3) +#define USART_CR1_RE (1 << 2) +#define USART_CR1_RWU (1 << 1) +#define USART_CR1_SBK (1 << 0) static struct USART * @@ -90,43 +104,50 @@ static const struct brr_setting brr_table[] = { static void *usart_main (void *arg); -struct usart_stat { - uint32_t tx; - uint32_t rx; - uint32_t rx_break; - uint32_t err_rx_overflow; /* software side */ - uint32_t err_rx_overrun; /* hardware side */ - uint32_t err_rx_noise; - uint32_t err_rx_parity; -}; - static struct usart_stat usart2_stat; static struct usart_stat usart3_stat; -void -usart_init (void) -{ - RCC->APB1ENR |= ((1 << 18) | (1 << 17)); - RCC->APB1RSTR = ((1 << 18) | (1 << 17)); - RCC->APB1RSTR = 0; - -} - -/* - * CONFIG_BITS includes - * baud_rate - * char-bit size - * stop-bit - * parity - * mode: Normal, LIN, Smartcard, etc. - * flow_ctrl - */ int usart_config (uint8_t dev_no, uint32_t config_bits) { struct USART *USARTx = get_usart_dev (dev_no); - uint8_t baud_spec = (config & 0x3f); + uint8_t baud_spec = (config & MASK_BAUD); int i; + uint32_t cr1_config = (USART_CR1_UE | USART_CR1_TXEIE | USART_CR1_RXNEIE + | USART_CR1_TE | USART_CR1_RE); + /* No CTSIE, PEIE, TCIE, IDLEIE, LBDIE */ + if (USARTx == NULL) + return -1; + + /* Disable USART before configure. */ + USARTx->CR1 &= ~USART_CR1_UE; + + if (((config_bits & MASK_CS) == CS7 && (config_bits & PARENB)) + || ((config_bits & MASK_CS) == CS8 && (config_bits & PARENB) == 0)) + cr1_config &= ~USART_CR1_M; + else if ((config_bits & MASK_CS) == CS8) + cr1_config |= USART_CR1_M; + else + return -1; + + if ((config_bits & PARENB) == 0) + cr1_config &= ~USART_CR1_PCE; + else + cr1_config |= USART_CR1_PCE; + + if ((config_bits & PARODD) == 0) + cr1_config &= ~USART_CR1_PS; + else + cr1_config |= USART_CR1_PS; + + if ((config_bits & MASK_STOP) == STOP0B5) + USARTx->CR2 = (0x1 << 12); + else if ((config_bits & MASK_STOP) == STOP1B) + USARTx->CR2 = (0x0 << 12); + else if ((config_bits & MASK_STOP) == STOP1B5) + USARTx->CR2 = (0x3 << 12); + else /* if ((config_bits & MASK_STOP) == STOP2B) */ + USARTx->CR2 = (0x2 << 12); for (i = 0; i < NUM_BAUD; i++) if (brr_table[i].baud_spec == baud_spec) @@ -137,10 +158,28 @@ usart_config (uint8_t dev_no, uint32_t config_bits) USARTx->BRR = brr_table[i].brr_value; - /* No PEIE, CTSIE, TCIE, IDLEIE, LBDIE */ + if ((config_bits & MASK_FLOW)) + USARTx->CR3 = (1 << 9) | (1 << 8); + else + USARTx->CR3 = 0; + + USARTx->CR1 = cr1_config; return 0; } +void +usart_init (uint16_t prio, uintptr_t stack_addr, size_t stack_size) +{ + /* Enable USART2 and USART3 clocks, and strobe reset. */ + RCC->APB1ENR |= ((1 << 18) | (1 << 17)); + RCC->APB1RSTR = ((1 << 18) | (1 << 17)); + RCC->APB1RSTR = 0; + + usart_config (2, B115200 | CS8 | STOP1B); + usart_config (3, B115200 | CS8 | STOP1B); + chopstx_create (prio, stack_addr, stack_size, usart_main, NULL); +} + /* * Ring buffer */ @@ -246,7 +285,7 @@ rb_ll_get (struct rng_rb *rb) * Application: consumer * Hardware: generator */ -int +static int rb_read (struct rng_rb *rb, uint8_t *buf, uint16_t buflen) { int i; @@ -271,7 +310,7 @@ rb_read (struct rng_rb *rb, uint8_t *buf, uint16_t buflen) * Application: generator * Hardware: consumer */ -void +static void rb_write (struct rng_rb *rb, uint8_t *buf, uint16_t buflen) { int i = 0; @@ -311,7 +350,7 @@ rb_get_prepare_poll (struct rb *rb, chopstx_poll_cond_t *poll_desc) poll_desc->check = rb_empty_check; poll_desc->arg = rb; } - + #define INTR_REQ_USART2 38 #define INTR_REQ_USART3 39 @@ -333,6 +372,7 @@ static chopstx_poll_cond_t usart3_app_write_event; static struct chx_poll_head * usart_poll[4]; +/* Global variables so that it can be easier to debug. */ static int usart2_tx_ready; static int usart3_tx_ready; @@ -371,6 +411,7 @@ handle_intr (struct USART *USARTx, struct rng_rb rb2a, struct usart_stat *stat) if ((r & USART_SR_ORE)) stat->err_rx_overrun++; + /* XXX: if CS is 7-bit, mask it, or else parity bit in upper layer */ if (rb_ll_put (rb2a, (data & 0xff)) < 0) stat->err_rx_overflow++; } @@ -387,7 +428,7 @@ handle_tx_ready (struct USART *USARTx, struct rng_rb rb2h, if (c >= 0) { - USARTx->DR = c; + USARTx->DR = (c & 0xff); USARTx->CR1 |= USART_CR1_TXEIE; stat->tx++; return 0; @@ -449,3 +490,45 @@ usart_main (void *arg) return NULL; } + +int +usart_read (uint8_t dev_no, uint8_t *buf, uint16_t buflen) +{ + struct rng_rb *rb; + + if (dev_no == 2) + rb = &usart2_rb_h2a; + else if (dev_no == 3) + rb = &usart3_rb_h2a; + else + return -1; + + return rb_read (rb, buf, buflen); +} + +int +usart_write (struct rng_rb *rb, uint8_t *buf, uint16_t buflen) +{ + struct rng_rb *rb; + + if (dev_no == 2) + rb = &usart2_rb_a2h; + else if (dev_no == 3) + rb = &usart3_rb_a2h; + else + return -1; + + rb_write (rb, buf, buflen); + return 0; +} + +const struct usart_stat * +usart_stat (uint8_t dev_no) +{ + if (dev_no == 2) + return &usart2_stat; + else if (dev_no == 3) + return &usart3_stat; + else + return NULL; +} diff --git a/contrib/usart.h b/contrib/usart.h index f8112e6..a523374 100644 --- a/contrib/usart.h +++ b/contrib/usart.h @@ -1,31 +1,36 @@ #define B0 0 /* POSIX to hang up */ /* POSIX supports B75 to B300 */ -#define B600 16 -#define B1200 17 -#define B2400 19 -#define B9600 21 -#define B19200 22 -#define B57600 24 -#define B115200 25 -#define B230400 26 -#define B460800 27 -#define B921600 28 +#define B600 16 +#define B1200 17 +#define B2400 19 +#define B9600 21 +#define B19200 22 +#define B57600 24 +#define B115200 25 +#define B230400 26 +#define B460800 27 +#define B921600 28 +#define MASK_BAUD 0x3f /* POSIX supports 5, 6. USB suppots 16 */ -#define CS7 (2 << 6) -#define CS8 (3 << 6) +#define CS7 (2 << 6) +#define CS8 (3 << 6) +#define MASK_CS (0x7 << 6) -#define STOP0B5 (0 << 9) /* Driver only */ -#define STOP1B (1 << 9) /* USB, POSIX */ -#define STOP1B5 (2 << 9) /* USB */ -#define STOP2B (3 << 9) /* USB, POSIX */ +#define STOP0B5 (0 << 9) /* USART Hardware only */ +#define STOP1B (1 << 9) /* USB, POSIX */ +#define STOP1B5 (2 << 9) /* USB */ +#define STOP2B (3 << 9) /* USB, POSIX */ +#define MASK_STOP (0x3 << 9) -#define PARENB (1 << 11) -#define PARODD (2 << 11) +#define PARENB (1 << 11) +#define PARODD (2 << 11) +#define MASK_PAR (0x7 << 11) /* USB 0: none, 1: odd, 2: even, 3: mark, 4: space */ -#define CRTSCTS (1 << 14) +#define CRTSCTS (1 << 14) +#define MASK_FLOW (0x1 << 14) /* BAUD_BITS 6 @@ -37,3 +42,19 @@ PAR_BITS 3 DTR RTS */ /* USB: SERIAL_STATE DSR DCD RI */ + +struct usart_stat { + uint32_t tx; + uint32_t rx; + uint32_t rx_break; + uint32_t err_rx_overflow; /* software side */ + uint32_t err_rx_overrun; /* hardware side */ + uint32_t err_rx_noise; + uint32_t err_rx_parity; +}; + +void usart_init (uint16_t prio, uintptr_t stack_addr, size_t stack_size); +int usart_config (uint8_t dev_no, uint32_t config_bits); +int usart_read (uint8_t dev_no, uint8_t *buf, uint16_t buflen); +int usart_write (struct rng_rb *rb, uint8_t *buf, uint16_t buflen); +const struct usart_stat *usart_stat (uint8_t dev_no);