123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- // From module: SERCOM Callback API
- #include <samd21.h>
- #include <sercom.h>
- // #include <sercom_interrupt.h>
- // From module: SERCOM USART - Serial Communications (Callback APIs)
- #include <usart.h>
- // #include <usart_interrupt.h>
- #include <rtdevice.h>
- typedef struct _samd2x_uart_t
- {
- struct rt_serial_device *serial;
- struct usart_module *instance;
- Sercom *com;
- enum usart_signal_mux_settings mux_setting;
- uint32_t pinmux_pad0;
- uint32_t pinmux_pad1;
- uint32_t pinmux_pad2;
- uint32_t pinmux_pad3;
- enum system_interrupt_vector vector;
- } SAMD2x_UART_T;
- static struct rt_serial_device _serial3;
- static struct usart_module _uart3_instance;
- static SAMD2x_UART_T _uart3 = {
- &_serial3,
- &_uart3_instance,
- SERCOM3,
- USART_RX_1_TX_0_XCK_1,
- PINMUX_PA22C_SERCOM3_PAD0,
- PINMUX_PA23C_SERCOM3_PAD1,
- PINMUX_UNUSED,
- PINMUX_UNUSED,
- SYSTEM_INTERRUPT_MODULE_SERCOM3
- };
- // static struct rt_serial_device _serial2;
- // static struct rt_serial_device _serial3;
- // static struct rt_serial_device _serial4;
- static rt_err_t _uart_cfg(struct rt_serial_device *serial, struct serial_configure *cfg)
- {
- SAMD2x_UART_T *uart;
- RT_ASSERT(serial != RT_NULL);
- RT_ASSERT(cfg != RT_NULL);
- uart = (SAMD2x_UART_T *)serial->parent.user_data;
- //! [setup_config]
- struct usart_config config_usart;
- //! [setup_config]
- //! [setup_config_defaults]
- usart_get_config_defaults(&config_usart);
- //! [setup_config_defaults]
- config_usart.baudrate = cfg->baud_rate;
- switch (cfg->data_bits )
- {
- case DATA_BITS_8:
- config_usart.character_size = USART_CHARACTER_SIZE_8BIT;
- break;
- case DATA_BITS_5:
- config_usart.character_size = USART_CHARACTER_SIZE_5BIT;
- break;
- case DATA_BITS_6:
- config_usart.character_size = USART_CHARACTER_SIZE_6BIT;
- break;
- case DATA_BITS_7:
- config_usart.character_size = USART_CHARACTER_SIZE_7BIT;
- break;
- case DATA_BITS_9:
- config_usart.character_size = USART_CHARACTER_SIZE_9BIT;
- break;
- default:
- config_usart.character_size = USART_CHARACTER_SIZE_8BIT;
- break;
- }
- switch (cfg->parity)
- {
- case PARITY_NONE:
- config_usart.parity = USART_PARITY_NONE;
- break;
- case PARITY_EVEN:
- config_usart.parity = USART_PARITY_EVEN;
- break;
- case PARITY_ODD:
- config_usart.parity = USART_PARITY_ODD;
- break;
- default:
- config_usart.parity = USART_PARITY_NONE;
- break;
- }
- config_usart.stopbits = USART_STOPBITS_1;
- if (cfg->stop_bits != USART_STOPBITS_1)
- {
- config_usart.stopbits = USART_STOPBITS_2;
- }
- config_usart.data_order = USART_DATAORDER_LSB;
- if (cfg->bit_order != BIT_ORDER_LSB)
- {
- config_usart.data_order = USART_DATAORDER_MSB;
- }
- config_usart.mux_setting = uart->mux_setting;
- config_usart.pinmux_pad0 = uart->pinmux_pad0;
- config_usart.pinmux_pad1 = uart->pinmux_pad1;
- config_usart.pinmux_pad2 = uart->pinmux_pad2;
- config_usart.pinmux_pad3 = uart->pinmux_pad3;
- config_usart.receiver_enable = false;
- config_usart.transmitter_enable = true;
- while (usart_init(uart->instance, uart->com, &config_usart) != STATUS_OK) {
- }
- usart_enable(uart->instance);
- /* Wait for the synchronization to complete */
- _usart_wait_for_sync(uart->instance);
- return RT_EOK;
- }
- static rt_err_t _uart_ctrl(struct rt_serial_device *serial, int cmd, void *arg)
- {
- SAMD2x_UART_T *uart;
- RT_ASSERT(serial != RT_NULL);
- uart = (SAMD2x_UART_T *)(serial->parent.user_data);
- switch (cmd)
- {
- /* disable interrupt */
- case RT_DEVICE_CTRL_CLR_INT:
- uart->com->USART.INTENCLR.reg = SERCOM_USART_INTFLAG_RXC;
- usart_disable_transceiver(uart->instance, USART_TRANSCEIVER_RX);
- system_interrupt_disable(uart->vector);
- /* Wait for the synchronization to complete */
- _usart_wait_for_sync(uart->instance);
- break;
- /* enable interrupt */
- case RT_DEVICE_CTRL_SET_INT:
- /* Enable RX interrupt. */
- /* Enable the RX Complete Interrupt */
- uart->com->USART.INTENSET.reg = SERCOM_USART_INTFLAG_RXC;
- usart_enable_transceiver(uart->instance, USART_TRANSCEIVER_RX);
- system_interrupt_enable(uart->vector);
- /* Wait for the synchronization to complete */
- _usart_wait_for_sync(uart->instance);
- break;
- default:
- return RT_ERROR;
- }
- return RT_EOK;
- }
- static int _uart_putc(struct rt_serial_device *serial, char c)
- {
- SAMD2x_UART_T *uart;
- RT_ASSERT(serial != RT_NULL);
- // while (!(uart->com->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_DRE)) {
- // }
- uart = (SAMD2x_UART_T *)(serial->parent.user_data);
- /* Write data to USART module */
- uart->com->USART.DATA.reg = c;
- while (!(uart->com->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC)) {
- /* Wait until data is sent */
- }
- return 1;
- }
- static int _uart_getc(struct rt_serial_device *serial)
- {
- int ch;
- SAMD2x_UART_T *uart;
- RT_ASSERT(serial != RT_NULL);
- uart = (SAMD2x_UART_T *)(serial->parent.user_data);
- /* Check if USART has new data */
- if (!(uart->com->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_RXC)) {
- /* Return error code */
- return -1;
- }
- ch = uart->com->USART.DATA.reg & 0x1FF;
- return ch;
- }
- static struct rt_uart_ops _uart_ops = {
- _uart_cfg,
- _uart_ctrl,
- _uart_putc,
- _uart_getc
- };
- static void uart_int_cb(SAMD2x_UART_T *uart_handle)
- {
- /* Temporary variables */
- uint16_t interrupt_status;
- uint8_t error_code;
- struct usart_module *module = uart_handle->instance;
- /* Pointer to the hardware module instance */
- SercomUsart *const usart_hw = &(module->hw->USART);
- /* Read and mask interrupt flag register */
- interrupt_status = usart_hw->INTFLAG.reg;
- interrupt_status &= usart_hw->INTENSET.reg;
- /* Check if the Receive Complete interrupt has occurred, and that
- * there's more data to receive */
- if (interrupt_status & SERCOM_USART_INTFLAG_RXC) {
- /* Read out the status code and mask away all but the 4 LSBs*/
- error_code = (uint8_t)(usart_hw->STATUS.reg & SERCOM_USART_STATUS_MASK);
- #if !SAMD20
- /* CTS status should not be considered as an error */
- if(error_code & SERCOM_USART_STATUS_CTS) {
- error_code &= ~SERCOM_USART_STATUS_CTS;
- }
- #endif
- #ifdef FEATURE_USART_LIN_MASTER
- /* TXE status should not be considered as an error */
- if(error_code & SERCOM_USART_STATUS_TXE) {
- error_code &= ~SERCOM_USART_STATUS_TXE;
- }
- #endif
- /* Check if an error has occurred during the receiving */
- if (error_code) {
- /* Check which error occurred */
- if (error_code & SERCOM_USART_STATUS_FERR) {
- /* clear flag by writing 1 to it */
- usart_hw->STATUS.reg = SERCOM_USART_STATUS_FERR;
- } else if (error_code & SERCOM_USART_STATUS_BUFOVF) {
- /* clear flag by writing 1 to it */
- usart_hw->STATUS.reg = SERCOM_USART_STATUS_BUFOVF;
- } else if (error_code & SERCOM_USART_STATUS_PERR) {
- /* clear flag by writing 1 to it */
- usart_hw->STATUS.reg = SERCOM_USART_STATUS_PERR;
- }
- #ifdef FEATURE_USART_LIN_SLAVE
- else if (error_code & SERCOM_USART_STATUS_ISF) {
- /* clear flag by writing 1 to it */
- usart_hw->STATUS.reg = SERCOM_USART_STATUS_ISF;
- }
- #endif
- #ifdef FEATURE_USART_COLLISION_DECTION
- else if (error_code & SERCOM_USART_STATUS_COLL) {
- /* clear flag by writing 1 to it */
- usart_hw->STATUS.reg = SERCOM_USART_STATUS_COLL;
- }
- #endif
- } else {
- rt_hw_serial_isr(uart_handle->serial, RT_SERIAL_EVENT_RX_IND);
- }
- }
- #ifdef FEATURE_USART_HARDWARE_FLOW_CONTROL
- if (interrupt_status & SERCOM_USART_INTFLAG_CTSIC) {
- /* Disable interrupts */
- usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_CTSIC;
- /* Clear interrupt flag */
- usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_CTSIC;
- }
- #endif
- #ifdef FEATURE_USART_LIN_SLAVE
- if (interrupt_status & SERCOM_USART_INTFLAG_RXBRK) {
- /* Disable interrupts */
- usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_RXBRK;
- /* Clear interrupt flag */
- usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_RXBRK;
- }
- #endif
- #ifdef FEATURE_USART_START_FRAME_DECTION
- if (interrupt_status & SERCOM_USART_INTFLAG_RXS) {
- /* Disable interrupts */
- usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_RXS;
- /* Clear interrupt flag */
- usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_RXS;
- }
- #endif
- }
- void SERCOM3_Handler(void)
- {
- uart_int_cb(&_uart3);
- }
- void uart_init(void)
- {
- struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
- config.bufsz = 512;
- _serial3.config = config;
- _serial3.ops = &_uart_ops;
- rt_hw_serial_register(&_serial3, "uart3", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, &_uart3);
- }
|