Files
microchip-application-bmd38…/uart.drv.c
T
2025-05-26 20:52:01 +08:00

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