summaryrefslogtreecommitdiff
path: root/app/src/com_task.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/com_task.c')
-rw-r--r--app/src/com_task.c279
1 files changed, 279 insertions, 0 deletions
diff --git a/app/src/com_task.c b/app/src/com_task.c
new file mode 100644
index 0000000..d6bc97d
--- /dev/null
+++ b/app/src/com_task.c
@@ -0,0 +1,279 @@
+
+#include "com_task.h"
+#include "can_task.h"
+#include "gpio_ext.h"
+#include "adc_task.h"
+
+volatile uint8_t registers[APALIS_TK1_K20_LAST_REG];
+volatile uint8_t regRxHandled;
+
+/* Put FW version at known address in a binary. Make it 32-bit to have room for the future */
+#ifndef TESTER_BUILD
+const uint32_t __attribute__((section(".FwVersion"), used)) fw_version = APALIS_TK1_K20_FW_VER;
+#else
+const uint32_t __attribute__((section(".FwVersion"), used)) fw_version = APALIS_TK1_K20_TESTER_FW_VER;
+#endif
+
+static dspi_slave_handle_t spi_handle;
+static uint8_t slaveRxData[APALIS_TK1_K20_MAX_BULK + APALIS_TK1_K20_HEADER];
+static uint8_t slaveTxData[APALIS_TK1_K20_MAX_BULK + APALIS_TK1_K20_HEADER];
+
+#ifdef SPI_DMA
+dspi_slave_edma_handle_t g_dspi_edma_s_handle;
+edma_handle_t dspiEdmaSlaveRxHandle;
+edma_handle_t dspiEdmaSlaveTxHandle;
+#endif
+
+void generate_irq(uint8_t irq) {
+ if (!(registers[APALIS_TK1_K20_MSQREG] & BIT(irq))) {
+ taskENTER_CRITICAL();
+ registers[APALIS_TK1_K20_IRQREG] |= BIT(irq);
+ /* Toggle INT1 pin */
+ GPIO_TogglePinsOutput(GPIOA, 1u << 16u);
+ taskEXIT_CRITICAL();
+ }
+}
+
+void clear_irq_flag(uint8_t irq) {
+ registers[APALIS_TK1_K20_IRQREG] &= ~irq;
+}
+
+uint8_t get_control_reg()
+{
+ return registers[APALIS_TK1_K20_CTRREG];
+
+}
+
+void set_control_reg(uint8_t value)
+{
+ registers[APALIS_TK1_K20_CTRREG] = value;
+}
+
+uint8_t get_status_reg()
+{
+ return registers[APALIS_TK1_K20_STAREG];
+
+}
+
+void set_status_reg(uint8_t value)
+{
+ registers[APALIS_TK1_K20_STAREG] = value;
+}
+
+uint8_t get_mask_reg()
+{
+ return registers[APALIS_TK1_K20_MSQREG];
+
+}
+
+void set_mask_reg(uint8_t value)
+{
+ registers[APALIS_TK1_K20_MSQREG] = value;
+}
+
+uint8_t get_irq_reg()
+{
+ return registers[APALIS_TK1_K20_IRQREG];
+
+}
+
+void set_irq_reg(uint8_t value)
+{
+ /* Clear IRQ flag on 1 */
+ clear_irq_flag(value);
+
+}
+
+inline int general_registers(dspi_transfer_t * spi_transfer)
+{
+ uint8_t *rx_buf = spi_transfer->rxData;
+
+ if (rx_buf[0] == APALIS_TK1_K20_WRITE_INST) {
+ switch (rx_buf[1]) {
+ case APALIS_TK1_K20_STAREG:
+ set_status_reg(rx_buf[2]);
+ return 1;
+ case APALIS_TK1_K20_REVREG:
+ return -ENOENT;
+ case APALIS_TK1_K20_IRQREG:
+ set_irq_reg(rx_buf[2]);
+ return 1;
+ case APALIS_TK1_K20_CTRREG:
+ set_control_reg(rx_buf[2]);
+ return 1;
+ case APALIS_TK1_K20_MSQREG:
+ set_mask_reg(rx_buf[2]);
+ return 1;
+ default:
+ return -ESRCH;
+ }
+ }
+
+
+ return -ENXIO;
+}
+
+
+inline void SPI_main_callback(status_t status, void *userData)
+{
+ callback_message_t * cb = (callback_message_t*) userData;
+ BaseType_t reschedule = pdFALSE;
+
+ if (status == kStatus_Success)
+ {
+ xSemaphoreGiveFromISR(cb->sem, &reschedule);
+ }
+#if 0
+ if (status == kStatus_DSPI_Error)
+ {
+ __NOP();
+ }
+#endif
+ portYIELD_FROM_ISR(reschedule);
+}
+
+static void SPI_callback(SPI_Type *base, dspi_slave_handle_t *handle, status_t status, void *userData)
+{
+ SPI_main_callback(status, userData);
+}
+
+static void SPI_EDMA_callback(SPI_Type *base, dspi_slave_edma_handle_t *handle, status_t status, void *userData)
+{
+ SPI_main_callback(status, userData);
+}
+
+static dspi_slave_config_t spi2_slaveConfig;
+
+static void SPI_init() {
+ gpio_pin_config_t gpio_out_config = {
+ kGPIO_DigitalOutput, 0,
+ };
+ GPIO_PinInit(GPIOD, 11u, &gpio_out_config);
+ /* Slave config */
+ spi2_slaveConfig.whichCtar = kDSPI_Ctar0;
+ spi2_slaveConfig.ctarConfig.bitsPerFrame = 8;
+ spi2_slaveConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh;
+ spi2_slaveConfig.ctarConfig.cpha = kDSPI_ClockPhaseSecondEdge;
+ spi2_slaveConfig.enableContinuousSCK = false;
+ spi2_slaveConfig.enableRxFifoOverWrite = true;
+ spi2_slaveConfig.enableModifiedTimingFormat = false;
+ spi2_slaveConfig.samplePoint = kDSPI_SckToSin0Clock;
+ PRINTF("SPI init \r\n");
+ DSPI_SlaveInit(SPI2, &spi2_slaveConfig);
+ DSPI_SlaveTransferCreateHandle(SPI2, &spi_handle, SPI_callback, spi_handle.userData);
+
+ /* Set dspi slave interrupt priority higher. */
+ NVIC_SetPriority(SPI2_IRQn, 5U);
+ GPIO_ClearPinsOutput(GPIOA, 1u << 29u); /* INT2 active */
+ PRINTF("SPI init done \r\n");
+
+}
+
+void spi_task(void *pvParameters) {
+ callback_message_t spi_msg;
+ dspi_transfer_t slaveXfer;
+ int ret = 0;
+ int can_read = -1;
+#ifdef SPI_DMA
+ uint32_t slaveRxChannel, slaveTxChannel;
+ edma_config_t userConfig;
+#endif
+
+ spi_msg.sem = xSemaphoreCreateBinary();
+ spi_handle.userData = &spi_msg;
+ SPI_init();
+#ifdef SPI_DMA
+ slaveRxChannel = 0U;
+ slaveTxChannel = 1U;
+
+ DMAMUX_Init(DMAMUX);
+ DMAMUX_SetSource(DMAMUX, slaveRxChannel, kDmaRequestMux0SPI2Rx);
+ DMAMUX_EnableChannel(DMAMUX, slaveRxChannel);
+ DMAMUX_SetSource(DMAMUX, slaveTxChannel, kDmaRequestMux0SPI2Tx);
+ DMAMUX_EnableChannel(DMAMUX, slaveTxChannel);
+
+ EDMA_GetDefaultConfig(&userConfig);
+ EDMA_Init(DMA0, &userConfig);
+
+ EDMA_CreateHandle(&dspiEdmaSlaveRxHandle, DMA0, slaveRxChannel);
+ EDMA_CreateHandle(&dspiEdmaSlaveTxHandle, DMA0, slaveTxChannel);
+
+ g_dspi_edma_s_handle.userData = &spi_msg;
+ DSPI_SlaveTransferCreateHandleEDMA(SPI2, &g_dspi_edma_s_handle, SPI_EDMA_callback,
+ &spi_msg, &dspiEdmaSlaveRxHandle, &dspiEdmaSlaveTxHandle);
+#endif
+ memset((uint8_t *)registers, 0x00, APALIS_TK1_K20_LAST_REG);
+ registers[APALIS_TK1_K20_REVREG] = APALIS_TK1_K20_FW_VER;
+ GPIO_SetPinsOutput(GPIOA, 1u << 29u); /* INT2 idle */
+ slaveXfer.configFlags = kDSPI_SlaveCtar0;
+
+ while(1){
+ slaveXfer.txData = NULL;/* no MISO traffic*/
+ slaveXfer.rxData = slaveRxData;
+ slaveXfer.dataSize = 3;
+ /* Wait for instructions from SoC */
+ ret = DSPI_SlaveTransferNonBlocking(SPI2, &spi_handle, &slaveXfer);
+ if ( ret == kStatus_Success) {
+ xSemaphoreTake(spi_msg.sem, portMAX_DELAY);
+
+ if (slaveRxData[0] != APALIS_TK1_K20_READ_INST) {
+ taskENTER_CRITICAL();
+ slaveXfer.txData = slaveTxData;
+ slaveXfer.rxData = slaveRxData;
+ if (slaveRxData[1] <= 0x05) {
+ ret = general_registers(&slaveXfer);
+#ifndef TESTER_BUILD
+ } else if ((slaveRxData[1] >= APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(0))
+ && (slaveRxData[1] <= APALIS_TK1_K20_CAN_OUT_BUF_END + APALIS_TK1_K20_CAN_DEV_OFFSET(0))) {
+ ret = canx_registers(&slaveXfer, 0);
+ can_read = 0;
+
+ } else if ((slaveRxData[1] >= APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(1))
+ && (slaveRxData[1] <= APALIS_TK1_K20_CAN_OUT_BUF_END + APALIS_TK1_K20_CAN_DEV_OFFSET(1))) {
+ ret = canx_registers(&slaveXfer, 1);
+ can_read = 1;
+#endif
+#ifdef BOARD_USES_ADC
+ } else if ((slaveRxData[1] >= APALIS_TK1_K20_ADCREG) && (slaveRxData[1] <= APALIS_TK1_K20_ADC_CH3H)) {
+ ret = adc_registers(&slaveXfer);
+
+ } else if ((slaveRxData[1] >= APALIS_TK1_K20_TSCREG) && (slaveRxData[1] <= APALIS_TK1_K20_TSC_YPH)) {
+ ret = tsc_registers(&slaveXfer);
+#endif
+ } else if ((slaveRxData[1] >= APALIS_TK1_K20_GPIOREG) && (slaveRxData[1] <= APALIS_TK1_K20_GPIO_STA)) {
+ ret = gpio_registers(&slaveXfer);
+ } else {
+ /* Register not defined */
+ ret = -EINVAL;
+ }
+
+ if (ret < 0) {
+ PRINTF("Invalid read/write ret = %d rx[0] = 0x%x, rx[1] = 0x%x, rx[2] = 0x%x\r\n",
+ ret, slaveRxData[0], slaveRxData[1], slaveRxData[2]);
+ }
+
+ if (slaveRxData[0] == APALIS_TK1_K20_BULK_READ_INST) {
+ slaveXfer.dataSize = ret;
+ slaveXfer.rxData = NULL;
+#ifdef SPI_DMA
+ DSPI_SlaveTransferEDMA(SPI2, &g_dspi_edma_s_handle, &slaveXfer);
+#else
+ DSPI_SlaveTransferNonBlocking(SPI2, &spi_handle, &slaveXfer);
+#endif
+ taskEXIT_CRITICAL();
+ xSemaphoreTake(spi_msg.sem, portMAX_DELAY);
+
+ if (can_read >= 0) {
+ can_spi_read_complete(can_read);
+ can_read = -1;
+ }
+ } else {
+ taskEXIT_CRITICAL();
+ }
+ }
+ } else {
+ /* Something went wrong, retry */
+ DSPI_SlaveTransferAbort(SPI2, &spi_handle);
+ }
+ }
+}