From 4d55f719bb2ac2875ad736e10f22a70eac7c3284 Mon Sep 17 00:00:00 2001 From: Dominik Sliwa Date: Mon, 12 Mar 2018 16:35:59 +0100 Subject: can, adc fixes CAN: -clear CANINTF_TX on read, this improves TX performance, -fix possible race-condition and implement errata 5641 ADC -allow for non-bulk read Signed-off-by: Dominik Sliwa --- drivers/fsl_dspi.c | 17 ++++++- drivers/fsl_flexcan.c | 11 ++--- source/adc_task.c | 4 +- source/can_task.c | 60 +++++++++++++++++------ source/can_task.h | 2 + source/com_task.c | 131 +++++++++++++++++++++++--------------------------- source/com_task.h | 2 +- source/main.c | 40 +++------------ 8 files changed, 138 insertions(+), 129 deletions(-) diff --git a/drivers/fsl_dspi.c b/drivers/fsl_dspi.c index 0da640a..cacb52a 100644 --- a/drivers/fsl_dspi.c +++ b/drivers/fsl_dspi.c @@ -1486,10 +1486,23 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; - if (handle->remainingSendByteCount == 0){ + if (handle->remainingSendByteCount == 0 && handle->rxData){ if ( *(handle->rxData - 2) == APALIS_TK1_K20_READ_INST) { base->PUSHR_SLAVE = registers[dataReceived]; + switch (dataReceived) + { + case APALIS_TK1_K20_IRQREG: + registers[APALIS_TK1_K20_IRQREG] = 0; + break; + case APALIS_TK1_K20_CANREG: + registers[APALIS_TK1_K20_CANREG] &= ~0x10; + break; + case APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_OFFSET: + registers[APALIS_TK1_K20_CANREG + + APALIS_TK1_K20_CAN_OFFSET] &= ~0x10; + break; + } } else { @@ -1505,7 +1518,7 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) } else { - dataSend = dataReceived; + dataSend = 0x44; } --handle->remainingSendByteCount; diff --git a/drivers/fsl_flexcan.c b/drivers/fsl_flexcan.c index 6c7e0bd..09add9e 100644 --- a/drivers/fsl_flexcan.c +++ b/drivers/fsl_flexcan.c @@ -1281,6 +1281,7 @@ void FLEXCAN_TransferHandleIRQ(CAN_Type *base, flexcan_handle_t *handle) /* Get current State of Message Buffer. */ switch (handle->mbState[result]) { +#if 0 /* Solve Rx Data Frame. */ case kFLEXCAN_StateRxData: status = FLEXCAN_ReadRxMb(base, result, handle->mbFrameBuf[result]); @@ -1300,19 +1301,15 @@ void FLEXCAN_TransferHandleIRQ(CAN_Type *base, flexcan_handle_t *handle) } FLEXCAN_TransferAbortReceive(base, handle, result); break; - +#endif + /* Solve Tx Remote Frame. */ + case kFLEXCAN_StateTxRemote: /* fall through */ /* Solve Tx Data Frame. */ case kFLEXCAN_StateTxData: status = kStatus_FLEXCAN_TxIdle; FLEXCAN_TransferAbortSend(base, handle, result); break; - /* Solve Tx Remote Frame. */ - case kFLEXCAN_StateTxRemote: - handle->mbState[result] = kFLEXCAN_StateRxRemote; - status = kStatus_FLEXCAN_TxSwitchToRx; - break; - default: status = kStatus_FLEXCAN_UnHandled; break; diff --git a/source/adc_task.c b/source/adc_task.c index 77d07af..3bb4714 100644 --- a/source/adc_task.c +++ b/source/adc_task.c @@ -111,8 +111,10 @@ void adc_task(void *pvParameters) for (i = 0; i < ADC0_CHANNEL_CNT;i ++){ channel.channelNumber = adc0_channels[i]; gen_regs.adc[i] = do_adc_conversion(ADC0, &channel); + registers[APALIS_TK1_K20_ADC_CH0L + 2 * i] = gen_regs.adc[i] & 0xFF; + registers[APALIS_TK1_K20_ADC_CH0L + 2 * i + 1] = (gen_regs.adc[i] >> 8) & 0xFF; } - vTaskDelay(1); + vTaskDelay(5); } } diff --git a/source/can_task.c b/source/can_task.c index 82b0dda..205e397 100644 --- a/source/can_task.c +++ b/source/can_task.c @@ -60,13 +60,31 @@ static uint8_t data_buffer[2][APALIS_TK1_CAN_RX_BUF_SIZE][CAN_TRANSFER_BUF_LEN]; static struct can_registers can_regs[2]; uint8_t resume_can; -void generate_can_irq(uint8_t id) { +void generate_can_irq(uint8_t id) +{ if (id == 0) GPIO_TogglePinsOutput(GPIOB, 1u << 8u); else GPIO_TogglePinsOutput(GPIOE, 1u << 26u); } +void can_tx_notify_task(void *pvParameters) +{ + uint32_t ulInterruptStatus; + + while(1){ + xTaskNotifyWait( 0x00, 0xFFFFFFFF, &ulInterruptStatus, portMAX_DELAY); + if (ulInterruptStatus & 0x01) { + registers[APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(0)] |= CANINTF_TX; + generate_can_irq(0); + } + if (ulInterruptStatus & 0x02) { + registers[APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(1)] |= CANINTF_TX; + generate_can_irq(1); + } + } +} + static void flexcan_callback0(CAN_Type *base, flexcan_handle_t *handle, status_t status, uint32_t result, void *userData) { callback_message_t * cb = (callback_message_t*) userData; @@ -82,9 +100,7 @@ static void flexcan_callback0(CAN_Type *base, flexcan_handle_t *handle, status_t case kStatus_FLEXCAN_TxIdle: if (TX_MESSAGE_BUFFER_NUM0 == result) { - /* write status and gen irq */ - registers[APALIS_TK1_K20_CANREG] |= CANINTF_TX; - generate_can_irq(0); + xTaskNotifyFromISR(can_tx_notify_task_handle, 0x01, eSetBits, &reschedule); } break; @@ -109,9 +125,7 @@ static void flexcan_callback1(CAN_Type *base, flexcan_handle_t *handle, status_t case kStatus_FLEXCAN_TxIdle: if (TX_MESSAGE_BUFFER_NUM0 == result) { - /* write status and gen irq */ - registers[APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_OFFSET] |= CANINTF_TX; - generate_can_irq(1); + xTaskNotifyFromISR(can_tx_notify_task_handle, 0x02, eSetBits, &reschedule); } break; @@ -142,15 +156,19 @@ static void CAN0_Init() FLEXCAN_SetRxMbGlobalMask(CAN0, FLEXCAN_RX_MB_EXT_MASK(0x00, 0, 0)); FLEXCAN_SetRxFifoGlobalMask(CAN0, FLEXCAN_RX_MB_EXT_MASK(0x00, 0, 0)); - /* Setup Tx Message Buffer. */ - FLEXCAN_SetTxMbConfig(CAN0, TX_MESSAGE_BUFFER_NUM0, true); - - fifoConfig.idFilterNum = 1; + fifoConfig.idFilterNum = 0; fifoConfig.idFilterTable = &fifoFilter; fifoConfig.idFilterType = kFLEXCAN_RxFifoFilterTypeC; fifoConfig.priority = kFLEXCAN_RxFifoPrioHigh; FLEXCAN_SetRxFifoConfig(CAN0, &fifoConfig, true); + /* errata #5641 */ + FLEXCAN_SetTxMbConfig(CAN0, TX_MESSAGE_BUFFER_NUM0 - 1, true); + + /* Setup Tx Message Buffer. */ + FLEXCAN_SetTxMbConfig(CAN0, TX_MESSAGE_BUFFER_NUM0, true); + memset(&can_regs[0], 0x00u,sizeof(struct can_registers)); + PRINTF("CAN0 init done \r\n"); } @@ -175,15 +193,19 @@ static void CAN1_Init() FLEXCAN_SetRxMbGlobalMask(CAN1, FLEXCAN_RX_MB_EXT_MASK(0x00, 0, 0)); FLEXCAN_SetRxFifoGlobalMask(CAN1, FLEXCAN_RX_MB_EXT_MASK(0x00, 0, 0)); - /* Setup Tx Message Buffer. */ - FLEXCAN_SetTxMbConfig(CAN1, TX_MESSAGE_BUFFER_NUM0, true); - - fifoConfig.idFilterNum = 1; + fifoConfig.idFilterNum = 0; fifoConfig.idFilterTable = &fifoFilter; fifoConfig.idFilterType = kFLEXCAN_RxFifoFilterTypeC; fifoConfig.priority = kFLEXCAN_RxFifoPrioHigh; FLEXCAN_SetRxFifoConfig(CAN1, &fifoConfig, true); + /* errata #5641 */ + FLEXCAN_SetTxMbConfig(CAN1, TX_MESSAGE_BUFFER_NUM0 - 1, true); + + /* Setup Tx Message Buffer. */ + FLEXCAN_SetTxMbConfig(CAN1, TX_MESSAGE_BUFFER_NUM0, true); + memset(&can_regs[0], 0x00u,sizeof(struct can_registers)); + PRINTF("CAN1 init done \r\n"); } uint8_t available_data[2]; @@ -244,7 +266,9 @@ void can0_task(void *pvParameters) { while(1) { + taskENTER_CRITICAL(); FLEXCAN_TransferReceiveFifoNonBlocking(CAN0, &flexcanHandle[0], &rxXfer); + taskEXIT_CRITICAL(); if (xSemaphoreTake(cb_msg.sem, portMAX_DELAY) == pdTRUE) { if (cb_msg.async_status == pdTRUE) { cb_msg.async_status = pdFALSE; @@ -274,7 +298,9 @@ void can1_task(void *pvParameters) { while(1) { + taskENTER_CRITICAL(); FLEXCAN_TransferReceiveFifoNonBlocking(CAN1, &flexcanHandle[1], &rxXfer); + taskEXIT_CRITICAL(); if (xSemaphoreTake(cb_msg.sem, portMAX_DELAY) == pdTRUE) { if (cb_msg.async_status == pdTRUE) { cb_msg.async_status = pdFALSE; @@ -363,7 +389,9 @@ uint8_t can0_transmit(){ txXfer.frame = &tx_frame[0]; txXfer.mbIdx = TX_MESSAGE_BUFFER_NUM0; + taskENTER_CRITICAL(); FLEXCAN_TransferSendNonBlocking(CAN0, &flexcanHandle[0], &txXfer); + taskEXIT_CRITICAL(); return 0; } @@ -373,7 +401,9 @@ uint8_t can1_transmit(){ txXfer.frame = &tx_frame[1]; txXfer.mbIdx = TX_MESSAGE_BUFFER_NUM0; + taskENTER_CRITICAL(); FLEXCAN_TransferSendNonBlocking(CAN1, &flexcanHandle[1], &txXfer); + taskEXIT_CRITICAL(); return 0; } diff --git a/source/can_task.h b/source/can_task.h index 564f073..9ad77f9 100644 --- a/source/can_task.h +++ b/source/can_task.h @@ -12,8 +12,10 @@ TaskHandle_t can0_task_handle; TaskHandle_t can1_task_handle; +TaskHandle_t can_tx_notify_task_handle; void can0_task(void *pvParameters); void can1_task(void *pvParameters); +void can_tx_notify_task(void *pvParameters); int canx_registers(dspi_transfer_t *spi_transfer, int id); void can_calculate_available_data(uint8_t id); diff --git a/source/com_task.c b/source/com_task.c index 1c814df..a141c40 100644 --- a/source/com_task.c +++ b/source/com_task.c @@ -4,7 +4,8 @@ #include "gpio_ext.h" #include "adc_task.h" -uint8_t registers[APALIS_TK1_K20_LAST_REG]; +volatile uint8_t registers[APALIS_TK1_K20_LAST_REG]; +volatile uint8_t regRxHandled; /* Put FW version at known address in binary. Make it 32-bit to have room for the future*/ const uint32_t __attribute__((section(".FwVersion"), used)) fw_version = APALIS_TK1_K20_FW_VER; @@ -180,92 +181,82 @@ void spi_task(void *pvParameters) { g_dspi_edma_s_handle.userData = &cb_msg; DSPI_SlaveTransferCreateHandleEDMA(SPI2, &g_dspi_edma_s_handle, SPI_callback, &cb_msg, &dspiEdmaSlaveRxHandle, &dspiEdmaSlaveTxHandle); #endif + memset(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(cb_msg.sem, portMAX_DELAY); - slaveXfer.txData = slaveTxData; + while(1){ + slaveXfer.txData = NULL;/* no MISO traffic*/ slaveXfer.rxData = slaveRxData; - - if (slaveRxData[0] == APALIS_TK1_K20_READ_INST) - { - /* clear interrupt flags on read; */ - if ( slaveRxData[1] == APALIS_TK1_K20_IRQREG) - { - registers[APALIS_TK1_K20_IRQREG] = 0; - } - } - else - { - if (slaveRxData[1] <= 0x05) { - ret = general_registers(&slaveXfer); - } 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); - - } 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); + slaveXfer.dataSize = 3; + /* Wait for instructions from SoC */ + ret = DSPI_SlaveTransferNonBlocking(SPI2, &spi_handle, &slaveXfer); + if ( ret == kStatus_Success) { + + xSemaphoreTake(cb_msg.sem, portMAX_DELAY); + + slaveXfer.txData = slaveTxData; + slaveXfer.rxData = slaveRxData; + if (slaveRxData[0] != APALIS_TK1_K20_READ_INST) { + if (slaveRxData[1] <= 0x05) { + ret = general_registers(&slaveXfer); + } 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); + + } 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); #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_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); + } 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; - } + } 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) { - slaveTxData[0] = TK1_K20_INVAL; - slaveTxData[1] = ret; - slaveTxData[2] = slaveRxData[0]; - slaveTxData[3] = slaveRxData[1]; - slaveTxData[4] = slaveRxData[2]; - slaveXfer.txData = slaveTxData; - ret = 5; - } + if (ret <= 0) { + slaveTxData[0] = TK1_K20_INVAL; + slaveTxData[1] = ret; + slaveTxData[2] = slaveRxData[0]; + slaveTxData[3] = slaveRxData[1]; + slaveTxData[4] = slaveRxData[2]; + slaveXfer.txData = slaveTxData; + ret = 5; + } - if (slaveRxData[0] == APALIS_TK1_K20_BULK_READ_INST) - { - slaveXfer.dataSize = ret; - //retry_size = slaveXfer.dataSize; - slaveXfer.rxData = slaveRxData; /* We're not expecting any MOSI traffic, but NULL messes up stuff */ + if (slaveRxData[0] == APALIS_TK1_K20_BULK_READ_INST) + { + slaveXfer.dataSize = ret; + slaveXfer.rxData = NULL; /* We're not expecting any MOSI traffic, but NULL messes up stuff */ #ifdef SPI_DMA - __disable_irq(); // just to make sure that high can irq rate will not interfere - DSPI_SlaveTransferEDMA(SPI2, &g_dspi_edma_s_handle, &slaveXfer); - __enable_irq(); + DSPI_SlaveTransferEDMA(SPI2, &g_dspi_edma_s_handle, &slaveXfer); #else - DSPI_SlaveTransferNonBlocking(SPI2, &spi_handle, &slaveXfer); + DSPI_SlaveTransferNonBlocking(SPI2, &spi_handle, &slaveXfer); #endif - xSemaphoreTake(cb_msg.sem, portMAX_DELAY); - if (resume_can != 0) { - if (resume_can == 1) { - vTaskResume(can0_task_handle); - can_calculate_available_data(0); - } - else { - vTaskResume(can1_task_handle); - can_calculate_available_data(1); + xSemaphoreTake(cb_msg.sem, portMAX_DELAY); + if (resume_can != 0) { + if (resume_can == 1) { + vTaskResume(can0_task_handle); + can_calculate_available_data(0); + } + else { + vTaskResume(can1_task_handle); + can_calculate_available_data(1); + } + resume_can = 0; } - resume_can = 0; } } + } } } -} diff --git a/source/com_task.h b/source/com_task.h index 72ca858..46728ac 100644 --- a/source/com_task.h +++ b/source/com_task.h @@ -165,7 +165,7 @@ struct register_struct { uint16_t tsc_yp; } gen_regs; -extern uint8_t registers[APALIS_TK1_K20_LAST_REG]; +extern volatile uint8_t registers[APALIS_TK1_K20_LAST_REG]; extern uint8_t resume_can; #endif /* COM_TASK_H_ */ diff --git a/source/main.c b/source/main.c index ad4e82b..d2f86c2 100644 --- a/source/main.c +++ b/source/main.c @@ -56,29 +56,6 @@ #define CONTROLLER_ID kUSB_ControllerEhci0 #endif -/* Task priorities. */ -#define debug_task_PRIORITY 1 -#define USB_HOST_INTERRUPT_PRIORITY (5U) - -/* Task handles */ - -TaskHandle_t usb_task_handle; -#ifdef SDK_DEBUGCONSOLE -TaskHandle_t debug_task_handle; -#endif - - -/*! - * @brief Debug task - */ -#ifdef SDK_DEBUGCONSOLE -static void debug_task(void *pvParameters) { - for (;;) { - vTaskDelay(10000); - PRINTF("Alive\r\n"); - } -} -#endif /*! * @brief Application entry point. */ @@ -107,6 +84,11 @@ int main(void) { PRINTF("create CAN1 task error\r\n"); } + if(xTaskCreate(can_tx_notify_task, "CAN_tx_notify_task", 64L / sizeof(portSTACK_TYPE), NULL, 3, &can_tx_notify_task_handle) != pdPASS) + { + PRINTF("create CAN TX notify task error\r\n"); + } + #ifdef BOARD_USES_ADC if(xTaskCreate(adc_task, "ADC_task", 1000L / sizeof(portSTACK_TYPE), NULL, 2, &adc_task_handle) != pdPASS) { @@ -119,18 +101,10 @@ int main(void) { } #endif -#ifdef SDK_DEBUGCONSOLE - if(xTaskCreate(debug_task, "Debug_task", configMINIMAL_STACK_SIZE, NULL, debug_task_PRIORITY, &debug_task_handle) != pdPASS) - { - PRINTF("create hello task error\r\n"); - } -#endif - - NVIC_SetPriority(CAN0_ORed_Message_buffer_IRQn, 5u); - NVIC_SetPriority(CAN1_ORed_Message_buffer_IRQn, 5u); + NVIC_SetPriority(CAN0_ORed_Message_buffer_IRQn, 6u); + NVIC_SetPriority(CAN1_ORed_Message_buffer_IRQn, 6u); NVIC_SetPriority(SPI2_IRQn, 5u); NVIC_SetPriority(DMA0_IRQn, 5u); - NVIC_SetPriorityGrouping( 0 ); vTaskStartScheduler(); for(;;) { /* Infinite loop to avoid leaving the main function */ -- cgit v1.2.3