244 lines
6.9 KiB
C
244 lines
6.9 KiB
C
#include "nrf.h"
|
|
#include "nrf_gpio.h"
|
|
#include "nrf_uarte.h"
|
|
|
|
#include "le_uart_srv.h"
|
|
#include "uart_drv.h"
|
|
|
|
#include "nrf_error.h"
|
|
|
|
#include "FreeRTOS.h"
|
|
#include "message_buffer.h"
|
|
#include "semphr.h"
|
|
#include "task.h"
|
|
|
|
#include <string.h>
|
|
|
|
#if (DEF_UARTE_ENABLED)
|
|
|
|
#define UART_TX_PIN NRF_GPIO_PIN_MAP(0, 6)
|
|
#define UART_RX_PIN NRF_GPIO_PIN_MAP(0, 8)
|
|
|
|
static MessageBufferHandle_t rx_message = NULL;
|
|
static MessageBufferHandle_t tx_message = NULL;
|
|
static SemaphoreHandle_t tx_done_sem = NULL;
|
|
|
|
void UARTE0_UART0_IRQHandler(void)
|
|
{
|
|
if (NRF_UARTE0->EVENTS_ENDTX)
|
|
{
|
|
NRF_UARTE0->EVENTS_ENDTX = 0;
|
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
xSemaphoreGiveFromISR(tx_done_sem, &xHigherPriorityTaskWoken);
|
|
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
}
|
|
}
|
|
|
|
ret_code_t uart_set_baud(uint32_t baudrate)
|
|
{
|
|
ret_code_t ret = NRF_SUCCESS;
|
|
|
|
vTaskSuspendAll();
|
|
|
|
NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Disabled;
|
|
switch (baudrate)
|
|
{
|
|
case 4800:
|
|
NRF_UARTE0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud4800;
|
|
break;
|
|
case 9600:
|
|
NRF_UARTE0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud9600;
|
|
break;
|
|
case 19200:
|
|
NRF_UARTE0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud19200;
|
|
break;
|
|
case 38400:
|
|
NRF_UARTE0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud38400;
|
|
break;
|
|
case 56000:
|
|
NRF_UARTE0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud56000;
|
|
break;
|
|
case 57600:
|
|
NRF_UARTE0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud57600;
|
|
break;
|
|
case 115200:
|
|
NRF_UARTE0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200;
|
|
break;
|
|
case 250000:
|
|
NRF_UARTE0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud250000;
|
|
break;
|
|
case 1000000:
|
|
NRF_UARTE0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1M;
|
|
break;
|
|
default:
|
|
ret = NRF_ERROR_INVALID_PARAM;
|
|
break;
|
|
}
|
|
NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Enabled;
|
|
|
|
xTaskResumeAll();
|
|
|
|
return ret;
|
|
}
|
|
|
|
void uart_tx_task(void *p_arg)
|
|
{
|
|
for (;;)
|
|
{
|
|
static uint8_t tx[2048];
|
|
size_t tx_size = xMessageBufferReceive(tx_message, tx, sizeof(tx), portMAX_DELAY);
|
|
if (tx_size)
|
|
{
|
|
NRF_UARTE0->TXD.PTR = (uint32_t)tx;
|
|
NRF_UARTE0->TXD.MAXCNT = tx_size;
|
|
NRF_UARTE0->EVENTS_ENDTX = 0;
|
|
NRF_UARTE0->EVENTS_TXSTOPPED = 0;
|
|
NRF_UARTE0->EVENTS_TXSTARTED = 0;
|
|
NRF_UARTE0->TASKS_STARTTX = 1;
|
|
NRF_UARTE0->INTENSET = UARTE_INTENSET_ENDTX_Msk;
|
|
if (xSemaphoreTake(tx_done_sem, pdMS_TO_TICKS(10000)) == pdFALSE)
|
|
{
|
|
NRF_UARTE0->TASKS_STOPTX = 1;
|
|
}
|
|
NRF_UARTE0->INTENCLR = UARTE_INTEN_ENDTX_Msk;
|
|
}
|
|
}
|
|
}
|
|
|
|
void uart_rx_task(void *p_arg)
|
|
{
|
|
static uint8_t rx[2][2048];
|
|
int idx = 0;
|
|
NRF_UARTE0->SHORTS = UARTE_SHORTS_ENDRX_STARTRX_Msk;
|
|
NRF_UARTE0->RXD.PTR = (uint32_t)rx[idx];
|
|
NRF_UARTE0->RXD.MAXCNT = sizeof(rx[idx]);
|
|
NRF_UARTE0->TASKS_STOPRX = 1;
|
|
NRF_UARTE0->TASKS_STARTRX = 1;
|
|
do {
|
|
} while (NRF_UARTE0->EVENTS_RXSTARTED == 0);
|
|
NRF_UARTE0->RXD.PTR = (uint32_t)rx[idx ^ 1];
|
|
NRF_UARTE0->RXD.MAXCNT = sizeof(rx[idx ^ 1]);
|
|
|
|
for (;;)
|
|
{
|
|
NRF_UARTE0->EVENTS_RXDRDY = 0;
|
|
|
|
do {
|
|
vTaskDelay(pdMS_TO_TICKS(5));
|
|
} while (NRF_UARTE0->EVENTS_RXDRDY == 0);
|
|
|
|
do {
|
|
NRF_UARTE0->EVENTS_RXDRDY = 0;
|
|
vTaskDelay(pdMS_TO_TICKS(5));
|
|
} while (NRF_UARTE0->EVENTS_RXDRDY == 1);
|
|
|
|
NRF_UARTE0->EVENTS_ENDRX = 0;
|
|
NRF_UARTE0->EVENTS_RXSTARTED = 0;
|
|
NRF_UARTE0->TASKS_STOPRX = 1;
|
|
|
|
do {
|
|
vTaskDelay(pdMS_TO_TICKS(1));
|
|
} while (NRF_UARTE0->EVENTS_RXSTARTED == 0);
|
|
|
|
NRF_UARTE0->RXD.PTR = (uint32_t)rx[idx];
|
|
NRF_UARTE0->RXD.MAXCNT = sizeof(rx[idx]);
|
|
|
|
xMessageBufferSend(rx_message, rx[idx], NRF_UARTE0->RXD.AMOUNT, portMAX_DELAY);
|
|
|
|
idx ^= 1;
|
|
}
|
|
}
|
|
|
|
void uart_rx_notify_task(void *p_arg)
|
|
{
|
|
for (;;)
|
|
{
|
|
static uint8_t buf[2048];
|
|
uint32_t recv_size = uart_recv(buf, sizeof(buf));
|
|
if (recv_size)
|
|
{
|
|
uint8_t *p = buf;
|
|
uint32_t loops = recv_size / BLE_UART_MAX_DATA_LEN;
|
|
uint32_t remain = recv_size % BLE_UART_MAX_DATA_LEN;
|
|
|
|
for (int i = 0; i < loops; i++)
|
|
{
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
if (le_uart_notify((void *)p, BLE_UART_MAX_DATA_LEN) == NRF_SUCCESS)
|
|
{
|
|
p += BLE_UART_MAX_DATA_LEN;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
vTaskDelay(pdMS_TO_TICKS(5));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (remain)
|
|
{
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
if (le_uart_notify((void *)p, remain) == NRF_SUCCESS)
|
|
{
|
|
p += BLE_UART_MAX_DATA_LEN;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
vTaskDelay(pdMS_TO_TICKS(5));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void uart_init(void)
|
|
{
|
|
rx_message = xMessageBufferCreate(4096);
|
|
tx_message = xMessageBufferCreate(2048);
|
|
tx_done_sem = xSemaphoreCreateBinary();
|
|
|
|
NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Disabled;
|
|
NRF_UARTE0->PSEL.TXD = UART_TX_PIN | (UARTE_PSEL_TXD_CONNECT_Connected << UARTE_PSEL_TXD_CONNECT_Pos);
|
|
NRF_UARTE0->PSEL.RXD = UART_RX_PIN | (UARTE_PSEL_RXD_CONNECT_Connected << UARTE_PSEL_RXD_CONNECT_Pos);
|
|
NRF_UARTE0->PSEL.CTS = 0;
|
|
NRF_UARTE0->PSEL.RTS = 0;
|
|
NRF_UARTE0->CONFIG = 0;
|
|
NRF_UARTE0->BAUDRATE = UARTE_BAUDRATE_BAUDRATE_Baud115200;
|
|
NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Enabled;
|
|
|
|
// Config uart tx pin
|
|
nrf_gpio_cfg(
|
|
UART_TX_PIN,
|
|
NRF_GPIO_PIN_DIR_OUTPUT,
|
|
NRF_GPIO_PIN_INPUT_DISCONNECT,
|
|
NRF_GPIO_PIN_NOPULL,
|
|
NRF_GPIO_PIN_H0H1,
|
|
NRF_GPIO_PIN_NOSENSE);
|
|
|
|
// Config uart rx pin
|
|
nrf_gpio_cfg_input(UART_RX_PIN, NRF_GPIO_PIN_PULLUP);
|
|
|
|
sd_nvic_SetPriority(UARTE0_UART0_IRQn, _PRIO_APP_LOWEST);
|
|
sd_nvic_EnableIRQ(UARTE0_UART0_IRQn);
|
|
|
|
xTaskCreate(uart_tx_task, "uart tx", 64, NULL, 4, NULL);
|
|
xTaskCreate(uart_rx_task, "uart rx", 64, NULL, 4, NULL);
|
|
xTaskCreate(uart_rx_notify_task, "uart rx notify", 128, NULL, 3, NULL);
|
|
}
|
|
|
|
int uart_send(void *p_data, uint32_t size)
|
|
{
|
|
return xMessageBufferSend(tx_message, p_data, size, portMAX_DELAY);
|
|
}
|
|
|
|
int uart_recv(void *p_data, uint32_t max_size)
|
|
{
|
|
return xMessageBufferReceive(rx_message, p_data, max_size, portMAX_DELAY);
|
|
}
|
|
#endif
|