LPCXpresso55S69_ESP_Hosted/src/app_nh_impl.c

351 lines
9.7 KiB
C

/* Board */
#include "board.h"
#include "clock_config.h"
#include "pin_mux.h"
/* FreeRTOS */
/* clang-format off */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* clang-format on */
/* SDK drivers */
#include "fsl_gpio.h"
#include "fsl_pint.h"
#include "fsl_spi.h"
/* Debug Console */
#include "fsl_debug_console.h"
/* Private */
#include "app_nh_impl.h"
static int app_nh_impl_spi_init(void);
static int app_nh_impl_pin_init(void);
static inline bool app_nh_impl_is_isr(void);
static void app_nh_impl_drdy_callback(pint_pin_int_t pintr, uint32_t pmatch_status);
static void app_nh_impl_hs_callback(pint_pin_int_t pintr, uint32_t pmatch_status);
static nh_ret_t app_nh_impl_ops_xfer(void *handle, uint8_t *tx_data, uint8_t *rx_data, uint32_t len);
static nh_ret_t app_nh_impl_ops_drdy_read(void *handle, bool *rdy);
static void app_nh_impl_cb_event(void *handle, uint8_t *payload);
static nh_ret_t app_nh_impl_buf_allocate(void *handle, uint8_t **buf, uint32_t size);
static nh_ret_t app_nh_impl_buf_free(void *handle, uint8_t *buf);
static nh_ret_t app_nh_impl_semaphore_create(void *handle, nh_osa_semaphore_t *sem);
static nh_ret_t app_nh_impl_semaphore_take(void *handle, nh_osa_semaphore_t sem, uint32_t timeout_msec);
static nh_ret_t app_nh_impl_semaphore_give(void *handle, nh_osa_semaphore_t sem);
static nh_ret_t app_nh_impl_semaphore_destroy(void *handle, nh_osa_semaphore_t sem);
static nh_ret_t app_nh_impl_queue_create(void *handle, nh_osa_queue_t *queue, uint32_t item_size, uint32_t max_length);
static nh_ret_t app_nh_impl_queue_enqueue(void *handle, nh_osa_queue_t queue, void *item, uint32_t timeout_msec);
static nh_ret_t app_nh_impl_queue_dequeue(void *handle, nh_osa_queue_t queue, void *item, uint32_t timeout_msec);
static nh_ret_t app_impl_queue_destroy(void *handle, nh_osa_queue_t queue);
static void app_nh_impl_shared_if_task(void *parameters);
static void app_nh_impl_ctrl_task(void *parameters);
static nh_osa_t s_nh_osa = {
.buf_allocate = app_nh_impl_buf_allocate,
.buf_free = app_nh_impl_buf_free,
.sem_create = app_nh_impl_semaphore_create,
.sem_give = app_nh_impl_semaphore_give,
.sem_take = app_nh_impl_semaphore_take,
.sem_destroy = app_nh_impl_semaphore_destroy,
.queue_create = app_nh_impl_queue_create,
.queue_enqueue = app_nh_impl_queue_enqueue,
.queue_dequeue = app_nh_impl_queue_dequeue,
.queue_destroy = app_impl_queue_destroy,
};
static nh_shared_if_t s_nh_shared_if = {
.osa = &s_nh_osa,
.ops =
{
.xfer = app_nh_impl_ops_xfer,
.drdy_read = app_nh_impl_ops_drdy_read,
},
.cb =
{
.event = app_nh_impl_cb_event,
},
};
static nh_ctrl_api_t s_nh_ctrl_api = {
.osa = &s_nh_osa,
.shared_if = &s_nh_shared_if,
};
int app_nh_impl_init(void) {
if (app_nh_impl_pin_init() != 0) {
return -1;
}
if (app_nh_impl_spi_init() != 0) {
return -2;
}
if (nh_shared_if_init(&s_nh_shared_if) != NH_RET_SUCCESS) {
return -3;
}
if (xTaskCreate(app_nh_impl_shared_if_task, "NH_SHARED_IF", 1024, &s_nh_shared_if, 2, NULL) != pdPASS) {
return -4;
}
if (nh_ctrl_api_init(&s_nh_ctrl_api) != NH_RET_SUCCESS) {
return -5;
}
if (xTaskCreate(app_nh_impl_ctrl_task, "NH_CTRL", 512, &s_nh_ctrl_api, 2, NULL) != pdPASS) {
return -6;
}
return 0;
}
static int app_nh_impl_spi_init(void) {
spi_master_config_t cfg;
/* Main Clock to SPI */
CLOCK_AttachClk(kMAIN_CLK_to_HSLSPI);
SPI_MasterGetDefaultConfig(&cfg);
cfg.baudRate_Bps = 20000000UL;
cfg.sselNum = kSPI_Ssel1;
cfg.phase = kSPI_ClockPhaseSecondEdge; /* SPI Mode 1 */
if (SPI_MasterInit(SPI8, &cfg, CLOCK_GetHsLspiClkFreq()) != kStatus_Success) {
return -1;
}
return 0;
}
static int app_nh_impl_pin_init(void) {
/* Configure pin interrupt */
PINT_Init(PINT);
PINT_PinInterruptConfig(PINT, kPINT_PinInt0, kPINT_PinIntEnableRiseEdge, app_nh_impl_hs_callback);
PINT_EnableCallbackByIndex(PINT, kPINT_PinInt1);
PINT_PinInterruptConfig(PINT, kPINT_PinInt1, kPINT_PinIntEnableRiseEdge, app_nh_impl_drdy_callback);
PINT_EnableCallbackByIndex(PINT, kPINT_PinInt1);
EnableIRQ(PIN_INT0_IRQn);
NVIC_SetPriority(PIN_INT0_IRQn, 5);
EnableIRQ(PIN_INT1_IRQn);
NVIC_SetPriority(PIN_INT1_IRQn, 5);
return 0;
}
static inline bool app_nh_impl_is_isr(void) {
if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) {
/* We are in ISR... */
return true;
}
return false;
}
static void app_nh_impl_drdy_callback(pint_pin_int_t pintr, uint32_t pmatch_status) {
/* If there's a packet to be received by host, the DRDY is set high. */
if (GPIO_PinRead(GPIO, BOARD_INITMIKROEPINS_ESP_HS_PORT, BOARD_INITMIKROEPINS_ESP_HS_PIN)) {
nh_shared_if_inject_data_ready(&s_nh_shared_if);
}
}
static void app_nh_impl_hs_callback(pint_pin_int_t pintr, uint32_t pmatch_status) {
/* If the DRDY is high when HS rises, there's another packet waiting... */
if (GPIO_PinRead(GPIO, BOARD_INITMIKROEPINS_ESP_DRDY_PORT, BOARD_INITMIKROEPINS_ESP_DRDY_PIN)) {
nh_shared_if_inject_data_ready(&s_nh_shared_if);
}
}
static nh_ret_t app_nh_impl_ops_drdy_read(void *handle, bool *rdy) {
if (GPIO_PinRead(GPIO, BOARD_INITMIKROEPINS_ESP_DRDY_PORT, BOARD_INITMIKROEPINS_ESP_DRDY_PIN)) {
*rdy = true;
} else {
*rdy = false;
}
return NH_RET_SUCCESS;
}
static nh_ret_t app_nh_impl_ops_xfer(void *handle, uint8_t *tx_data, uint8_t *rx_data, uint32_t len) {
spi_transfer_t xfer = {
.txData = tx_data,
.rxData = rx_data,
.dataSize = len,
.configFlags = kSPI_FrameAssert,
};
if (SPI_MasterTransferBlocking(SPI8, &xfer) != kStatus_Success) {
return NH_RET_FAIL;
}
return NH_RET_SUCCESS;
}
static void app_nh_impl_cb_event(void *handle, uint8_t *payload) {
PRINTF("Received event from ESP..\r\n");
}
static nh_ret_t app_nh_impl_buf_allocate(void *handle, uint8_t **buf, uint32_t size) {
*buf = pvPortMalloc(size);
if (*buf == NULL) {
return NH_RET_FAIL;
}
return NH_RET_SUCCESS;
}
static nh_ret_t app_nh_impl_buf_free(void *handle, uint8_t *buf) {
vPortFree(buf);
return NH_RET_SUCCESS;
}
static nh_ret_t app_nh_impl_semaphore_create(void *handle, nh_osa_semaphore_t *sem) {
*sem = xSemaphoreCreateBinary();
if (*sem == NULL) {
return NH_RET_FAIL;
}
return NH_RET_SUCCESS;
}
static nh_ret_t app_nh_impl_semaphore_take(void *handle, nh_osa_semaphore_t sem, uint32_t timeout_msec) {
nh_ret_t ret = NH_RET_SUCCESS;
if (app_nh_impl_is_isr()) {
if (timeout_msec != 0) {
/* Block in ISR is not permitted */
return NH_RET_FAIL;
}
BaseType_t higher_prio_task_woken = pdFALSE;
if (xSemaphoreTakeFromISR(sem, &higher_prio_task_woken) != pdPASS) {
ret = NH_RET_TIMEOUT;
}
portYIELD_FROM_ISR(higher_prio_task_woken);
} else {
if (xSemaphoreTake(sem, pdMS_TO_TICKS(timeout_msec)) != pdPASS) {
ret = NH_RET_TIMEOUT;
}
}
return ret;
}
static nh_ret_t app_nh_impl_semaphore_give(void *handle, nh_osa_semaphore_t sem) {
nh_ret_t ret = NH_RET_SUCCESS;
if (app_nh_impl_is_isr()) {
BaseType_t higher_prio_task_woken = pdFALSE;
if (xSemaphoreGiveFromISR(sem, &higher_prio_task_woken) != pdPASS) {
ret = NH_RET_FAIL;
}
portYIELD_FROM_ISR(higher_prio_task_woken);
} else {
if (xSemaphoreGive(sem) != pdPASS) {
ret = NH_RET_FAIL;
}
}
return ret;
}
static nh_ret_t app_nh_impl_semaphore_destroy(void *handle, nh_osa_semaphore_t sem) {
vSemaphoreDelete(sem);
return NH_RET_SUCCESS;
}
static nh_ret_t app_nh_impl_queue_create(void *handle, nh_osa_queue_t *queue, uint32_t item_size, uint32_t max_length) {
*queue = xQueueCreate(max_length, item_size);
if (*queue == NULL) {
return NH_RET_FAIL;
}
return NH_RET_SUCCESS;
}
static nh_ret_t app_nh_impl_queue_enqueue(void *handle, nh_osa_queue_t queue, void *item, uint32_t timeout_msec) {
nh_ret_t ret = NH_RET_SUCCESS;
if (app_nh_impl_is_isr()) {
if (timeout_msec != 0) {
return NH_RET_FAIL;
}
BaseType_t higher_prio_task_woken = pdFALSE;
if (xQueueSendFromISR(queue, item, &higher_prio_task_woken) != pdPASS) {
ret = NH_RET_TIMEOUT;
}
portYIELD_FROM_ISR(higher_prio_task_woken);
} else {
if (xQueueSend(queue, item, pdMS_TO_TICKS(timeout_msec)) != pdPASS) {
ret = NH_RET_TIMEOUT;
}
}
return ret;
}
static nh_ret_t app_nh_impl_queue_dequeue(void *handle, nh_osa_queue_t queue, void *item, uint32_t timeout_msec) {
nh_ret_t ret = NH_RET_SUCCESS;
if (app_nh_impl_is_isr()) {
if (timeout_msec != 0) {
return NH_RET_FAIL;
}
BaseType_t higher_prio_task_woken = pdFALSE;
if (xQueueReceiveFromISR(queue, item, &higher_prio_task_woken) != pdPASS) {
ret = NH_RET_TIMEOUT;
}
portYIELD_FROM_ISR(higher_prio_task_woken);
} else {
if (xQueueReceive(queue, item, pdMS_TO_TICKS(timeout_msec)) != pdPASS) {
ret = NH_RET_TIMEOUT;
}
}
return ret;
}
static nh_ret_t app_impl_queue_destroy(void *handle, nh_osa_queue_t queue) {
vQueueDelete(queue);
return NH_RET_SUCCESS;
}
static void app_nh_impl_shared_if_task(void *parameters) {
for (;;) {
nh_shared_if_task(&s_nh_shared_if);
}
vTaskDelete(NULL);
}
static void app_nh_impl_ctrl_task(void *parameters) {
for (;;) {
nh_ctrl_api_task(&s_nh_ctrl_api);
}
vTaskDelete(NULL);
}