|
| 1 | +#include "board.h" |
| 2 | +#include "drv_uart.h" |
| 3 | + |
| 4 | +#include "nrf_drv_common.h" |
| 5 | +#include "nrf_drv_uart.h" |
| 6 | +#include "app_util_platform.h" |
| 7 | +#include "nrf_gpio.h" |
| 8 | + |
| 9 | +#include <rtdevice.h> |
| 10 | + |
| 11 | +static struct rt_serial_device _serial0_0; |
| 12 | +#if USE_UART0_1 |
| 13 | +static struct rt_serial_device _serial0_1; |
| 14 | +#endif |
| 15 | + |
| 16 | +typedef struct |
| 17 | +{ |
| 18 | + struct rt_serial_device *serial; |
| 19 | + nrf_drv_uart_t uart; |
| 20 | + uint32_t rx_pin; |
| 21 | + uint32_t tx_pin; |
| 22 | +} UART_CFG_T; |
| 23 | + |
| 24 | +UART_CFG_T uart0 = { |
| 25 | + .uart = NRF_DRV_UART_INSTANCE(0), |
| 26 | +#ifdef RT_USING_CONSOLE |
| 27 | + .rx_pin = 8, |
| 28 | + .tx_pin = 6 |
| 29 | +#else |
| 30 | + .rx_pin = 19, |
| 31 | + .tx_pin = 20 |
| 32 | +#endif |
| 33 | +}; |
| 34 | + |
| 35 | +#if USE_UART0_1 |
| 36 | +UART_CFG_T uart1 = { |
| 37 | + .uart = NRF_DRV_UART_INSTANCE(0), |
| 38 | + .rx_pin = 3, |
| 39 | + .tx_pin = 4 |
| 40 | +}; |
| 41 | +#endif |
| 42 | + |
| 43 | +UART_CFG_T *working_cfg = RT_NULL; |
| 44 | + |
| 45 | +void UART0_IRQHandler(void) |
| 46 | +{ |
| 47 | + if (nrf_uart_int_enable_check(NRF_UART0, NRF_UART_INT_MASK_ERROR) |
| 48 | + && nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_ERROR)) |
| 49 | + { |
| 50 | + nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_ERROR); |
| 51 | + } |
| 52 | + |
| 53 | + if (nrf_uart_int_enable_check(NRF_UART0, NRF_UART_INT_MASK_RXDRDY) |
| 54 | + && nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_RXDRDY)) |
| 55 | + { |
| 56 | + rt_hw_serial_isr(working_cfg->serial, RT_SERIAL_EVENT_RX_IND); |
| 57 | + } |
| 58 | + |
| 59 | + if (nrf_uart_int_enable_check(NRF_UART0, NRF_UART_INT_MASK_TXDRDY) |
| 60 | + && nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_TXDRDY)) |
| 61 | + { |
| 62 | + rt_hw_serial_isr(working_cfg->serial, RT_SERIAL_EVENT_TX_DONE); |
| 63 | + } |
| 64 | + |
| 65 | + if (nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_RXTO)) |
| 66 | + { |
| 67 | + rt_hw_serial_isr(working_cfg->serial, RT_SERIAL_EVENT_RX_TIMEOUT); |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +static rt_err_t _uart_cfg(struct rt_serial_device *serial, struct serial_configure *cfg) |
| 72 | +{ |
| 73 | + nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG; |
| 74 | + UART_CFG_T *instance = &uart0; |
| 75 | + |
| 76 | + RT_ASSERT(serial != RT_NULL); |
| 77 | + RT_ASSERT(cfg != RT_NULL); |
| 78 | + |
| 79 | + if (serial->parent.user_data != RT_NULL) |
| 80 | + { |
| 81 | + instance = (UART_CFG_T*)serial->parent.user_data; |
| 82 | + } |
| 83 | + |
| 84 | + nrf_uart_disable(instance->uart.reg.p_uart); |
| 85 | + |
| 86 | + switch (cfg->baud_rate) |
| 87 | + { |
| 88 | + case 115200: |
| 89 | + config.baudrate = NRF_UART_BAUDRATE_115200; |
| 90 | + break; |
| 91 | + |
| 92 | + case 9600: |
| 93 | + config.baudrate = NRF_UART_BAUDRATE_9600; |
| 94 | + break; |
| 95 | + |
| 96 | + default: |
| 97 | + config.baudrate = NRF_UART_BAUDRATE_115200; |
| 98 | + break; |
| 99 | + } |
| 100 | + |
| 101 | + if (cfg->parity == PARITY_NONE) |
| 102 | + { |
| 103 | + config.parity = NRF_UART_PARITY_EXCLUDED; |
| 104 | + } |
| 105 | + else |
| 106 | + { |
| 107 | + config.parity = NRF_UART_PARITY_INCLUDED; |
| 108 | + } |
| 109 | + |
| 110 | + config.hwfc = NRF_UART_HWFC_DISABLED; |
| 111 | + config.interrupt_priority = APP_IRQ_PRIORITY_LOWEST; |
| 112 | + config.pselcts = 0; |
| 113 | + config.pselrts = 0; |
| 114 | + config.pselrxd = instance->rx_pin; |
| 115 | + config.pseltxd = instance->tx_pin; |
| 116 | + |
| 117 | + nrf_gpio_pin_set(config.pseltxd); |
| 118 | + nrf_gpio_cfg_output(config.pseltxd); |
| 119 | + nrf_gpio_pin_clear(config.pseltxd); |
| 120 | + nrf_gpio_cfg_input(config.pselrxd, NRF_GPIO_PIN_NOPULL); |
| 121 | + nrf_uart_baudrate_set(instance->uart.reg.p_uart, config.baudrate); |
| 122 | + nrf_uart_configure(instance->uart.reg.p_uart, config.parity, config.hwfc); |
| 123 | + nrf_uart_txrx_pins_set(instance->uart.reg.p_uart, config.pseltxd, config.pselrxd); |
| 124 | + |
| 125 | + if (config.hwfc == NRF_UART_HWFC_ENABLED) |
| 126 | + { |
| 127 | + nrf_uart_hwfc_pins_set(instance->uart.reg.p_uart, config.pselrts, config.pselcts); |
| 128 | + } |
| 129 | + |
| 130 | + nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_TXDRDY); |
| 131 | + nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_RXDRDY); |
| 132 | + nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_RXTO); |
| 133 | + nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_ERROR); |
| 134 | + |
| 135 | + nrf_uart_int_enable(instance->uart.reg.p_uart, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_RXTO | NRF_UART_INT_MASK_ERROR); |
| 136 | + nrf_drv_common_irq_enable(nrf_drv_get_IRQn((void *)instance->uart.reg.p_uart), config.interrupt_priority); |
| 137 | + nrf_uart_enable(instance->uart.reg.p_uart); |
| 138 | + // nrf_uart_task_trigger(instance->uart.reg.p_uart, NRF_UART_TASK_STARTRX); |
| 139 | + working_cfg = instance; |
| 140 | + return RT_EOK; |
| 141 | +} |
| 142 | + |
| 143 | +static rt_err_t _uart_ctrl(struct rt_serial_device *serial, int cmd, void *arg) |
| 144 | +{ |
| 145 | + UART_CFG_T *instance = working_cfg; |
| 146 | + |
| 147 | + RT_ASSERT(serial != RT_NULL); |
| 148 | + |
| 149 | + if (serial->parent.user_data != RT_NULL) |
| 150 | + { |
| 151 | + instance = (UART_CFG_T*)serial->parent.user_data; |
| 152 | + } |
| 153 | + |
| 154 | + switch (cmd) |
| 155 | + { |
| 156 | + /* disable interrupt */ |
| 157 | + case RT_DEVICE_CTRL_CLR_INT: |
| 158 | + nrf_uart_task_trigger(instance->uart.reg.p_uart, NRF_UART_TASK_STOPRX); |
| 159 | + nrf_uart_int_disable(instance->uart.reg.p_uart, NRF_UART_INT_MASK_RXDRDY |
| 160 | + | NRF_UART_INT_MASK_RXTO |
| 161 | + | NRF_UART_INT_MASK_ERROR); |
| 162 | + nrf_drv_common_irq_disable(nrf_drv_get_IRQn((void *)instance->uart.reg.p_uart)); |
| 163 | + break; |
| 164 | + |
| 165 | + /* enable interrupt */ |
| 166 | + case RT_DEVICE_CTRL_SET_INT: |
| 167 | + nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_RXDRDY); |
| 168 | + nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_RXTO); |
| 169 | + nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_ERROR); |
| 170 | + /* Enable RX interrupt. */ |
| 171 | + nrf_uart_int_enable(instance->uart.reg.p_uart, NRF_UART_INT_MASK_RXDRDY |
| 172 | + | NRF_UART_INT_MASK_RXTO |
| 173 | + | NRF_UART_INT_MASK_ERROR); |
| 174 | + nrf_drv_common_irq_enable(nrf_drv_get_IRQn((void *)instance->uart.reg.p_uart), APP_IRQ_PRIORITY_LOWEST); |
| 175 | + nrf_uart_task_trigger(instance->uart.reg.p_uart, NRF_UART_TASK_STARTRX); |
| 176 | + break; |
| 177 | + |
| 178 | + case RT_DEVICE_CTRL_CUSTOM: |
| 179 | + if ((rt_uint32_t)(arg) == UART_CONFIG_BAUD_RATE_9600) |
| 180 | + { |
| 181 | + instance->serial->config.baud_rate = 9600; |
| 182 | + nrf_uart_baudrate_set(instance->uart.reg.p_uart, NRF_UART_BAUDRATE_9600); |
| 183 | + } |
| 184 | + else if ((rt_uint32_t)(arg) == UART_CONFIG_BAUD_RATE_115200) |
| 185 | + { |
| 186 | + instance->serial->config.baud_rate = 115200; |
| 187 | + nrf_uart_baudrate_set(instance->uart.reg.p_uart, NRF_UART_BAUDRATE_115200); |
| 188 | + } |
| 189 | + |
| 190 | + // _uart_cfg(instance->serial, &(instance->serial->config)); |
| 191 | + // nrf_uart_task_trigger(instance->uart.reg.p_uart, NRF_UART_TASK_STARTRX); |
| 192 | + break; |
| 193 | + |
| 194 | + case RT_DEVICE_CTRL_PIN: |
| 195 | + if (working_cfg != instance) |
| 196 | + { |
| 197 | + _uart_cfg(instance->serial, &(instance->serial->config)); |
| 198 | + } |
| 199 | + break; |
| 200 | + |
| 201 | + case RT_DEVICE_POWERSAVE: |
| 202 | + nrf_uart_disable(instance->uart.reg.p_uart); |
| 203 | + nrf_uart_txrx_pins_disconnect(instance->uart.reg.p_uart); |
| 204 | + nrf_gpio_pin_clear(instance->rx_pin); |
| 205 | + nrf_gpio_cfg_output(instance->rx_pin); |
| 206 | + nrf_gpio_pin_clear(instance->tx_pin); |
| 207 | + nrf_gpio_cfg_output(instance->tx_pin); |
| 208 | + break; |
| 209 | + |
| 210 | + case RT_DEVICE_WAKEUP: |
| 211 | + _uart_cfg(instance->serial, &(instance->serial->config)); |
| 212 | + break; |
| 213 | + |
| 214 | + default: |
| 215 | + return RT_ERROR; |
| 216 | + } |
| 217 | + |
| 218 | + return RT_EOK; |
| 219 | +} |
| 220 | + |
| 221 | +static int _uart_putc(struct rt_serial_device *serial, char c) |
| 222 | +{ |
| 223 | + UART_CFG_T *instance = working_cfg; |
| 224 | + |
| 225 | + RT_ASSERT(serial != RT_NULL); |
| 226 | + |
| 227 | + if (serial->parent.user_data != RT_NULL) |
| 228 | + { |
| 229 | + instance = (UART_CFG_T*)serial->parent.user_data; |
| 230 | + } |
| 231 | + |
| 232 | + nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_TXDRDY); |
| 233 | + nrf_uart_task_trigger(instance->uart.reg.p_uart, NRF_UART_TASK_STARTTX); |
| 234 | + nrf_uart_txd_set(instance->uart.reg.p_uart, (uint8_t)c); |
| 235 | + while (!nrf_uart_event_check(instance->uart.reg.p_uart, NRF_UART_EVENT_TXDRDY)) |
| 236 | + { |
| 237 | + } |
| 238 | + |
| 239 | + return 1; |
| 240 | +} |
| 241 | + |
| 242 | +static int _uart_getc(struct rt_serial_device *serial) |
| 243 | +{ |
| 244 | + int ch = -1; |
| 245 | + UART_CFG_T *instance = working_cfg; |
| 246 | + |
| 247 | + RT_ASSERT(serial != RT_NULL); |
| 248 | + |
| 249 | + if (serial->parent.user_data != RT_NULL) |
| 250 | + { |
| 251 | + instance = (UART_CFG_T*)serial->parent.user_data; |
| 252 | + } |
| 253 | + |
| 254 | + if (nrf_uart_event_check(instance->uart.reg.p_uart, NRF_UART_EVENT_RXDRDY)) |
| 255 | + { |
| 256 | + nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_RXDRDY); |
| 257 | + ch = (int)(nrf_uart_rxd_get(instance->uart.reg.p_uart)); |
| 258 | + } |
| 259 | + |
| 260 | + return ch; |
| 261 | +} |
| 262 | + |
| 263 | +static struct rt_uart_ops _uart_ops = { |
| 264 | + _uart_cfg, |
| 265 | + _uart_ctrl, |
| 266 | + _uart_putc, |
| 267 | + _uart_getc |
| 268 | +}; |
| 269 | + |
| 270 | +void rt_hw_uart_init(void) |
| 271 | +{ |
| 272 | + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; |
| 273 | + |
| 274 | + config.bufsz = RT_SERIAL_RB_BUFSZ; |
| 275 | + _serial0_0.config = config; |
| 276 | + _serial0_0.ops = &_uart_ops; |
| 277 | + uart0.serial = &_serial0_0; |
| 278 | + |
| 279 | + rt_hw_serial_register(&_serial0_0, "uart0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, &uart0); |
| 280 | + |
| 281 | +#if USE_UART0_1 |
| 282 | + config.bufsz = UART0_RB_SIZE; |
| 283 | + _serial0_1.config = config; |
| 284 | + _serial0_1.ops = &_uart_ops; |
| 285 | + uart1.serial = &_serial0_1; |
| 286 | + rt_hw_serial_register(&_serial0_1, "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, &uart1); |
| 287 | +#endif |
| 288 | +} |
| 289 | + |
0 commit comments