summaryrefslogtreecommitdiff
path: root/source/can_task.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/can_task.c')
-rw-r--r--source/can_task.c168
1 files changed, 115 insertions, 53 deletions
diff --git a/source/can_task.c b/source/can_task.c
index bab19ac..e34d35d 100644
--- a/source/can_task.c
+++ b/source/can_task.c
@@ -14,19 +14,13 @@
#define CAN_HEADER_MAX_LEN 5
#define CAN_TRANSFER_BUF_LEN (CAN_HEADER_MAX_LEN + CAN_FRAME_MAX_LEN)
-#define CAN_CTRLMODE_NORMAL 0x00 /* normal mode */
-#define CAN_CTRLMODE_LOOPBACK 0x01 /* Loopback mode */
-#define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */
-#define CAN_CTRLMODE_3_SAMPLES 0x04 /* Triple sampling mode */
-#define CAN_CTRLMODE_ONE_SHOT 0x08 /* One-Shot mode */
-#define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */
-
-#define CANCTRL_MODMASK 0x03
-#define CANCTRL_INTMASK 0x38
-#define CANCTRL_INTEN BIT(2)
-#define CANINTF_RX BIT(3)
-#define CANINTF_TX BIT(4)
-#define CANINTF_ERR BIT(5)
+#define CANCTRL_MODMASK (BIT(1) | BIT(0))
+#define CANCTRL_INTEN BIT(2)
+#define CANINTF_RX BIT(3)
+#define CANINTF_TX BIT(4)
+#define CANINTF_ERR BIT(5)
+#define CANCTRL_ENABLE BIT(6)
+#define CANCTRL_INTMASK (CANINTF_RX | CANINTF_TX | CANINTF_ERR)
#define EFLG_EWARN 0x01
#define EFLG_RXWAR 0x02
@@ -39,24 +33,26 @@
struct can_registers {
CAN_Type *base;
flexcan_handle_t handle;
- uint8_t can_status_reg;
+ uint8_t can_enable;
uint8_t can_err_reg;
uint8_t can_mode;
uint8_t frames_in_buf;
uint8_t rx_buf_top;
uint8_t rx_buf_bottom;
+ uint8_t tx_counter;
};
static uint8_t data_buffer[2][CAN_RX_BUF_SIZE][CAN_TRANSFER_BUF_LEN];
static struct can_registers can_regs[2];
-static void generate_can_irq(uint8_t id)
+static inline void generate_can_irq(uint8_t id)
{
- if (id == 0)
+ if (id == 0) {
GPIO_TogglePinsOutput(GPIOB, 1u << 8u);
- else
+ } else {
GPIO_TogglePinsOutput(GPIOE, 1u << 26u);
+ }
}
void can_tx_notify_task(void *pvParameters)
@@ -66,17 +62,25 @@ void can_tx_notify_task(void *pvParameters)
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;
+ 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;
+ registers[APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(1)] &= ~CANINTF_TX;
+ generate_can_irq(1);
+ }
+ if (ulInterruptStatus & 0x04) {
+ registers[APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(0)] |= CANINTF_ERR;
+ generate_can_irq(0);
+ }
+ if (ulInterruptStatus & 0x08) {
+ registers[APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(1)] |= CANINTF_ERR;
generate_can_irq(1);
}
}
}
-static void flexcan_callback(CAN_Type *base, flexcan_handle_t *handle, status_t status, uint32_t result, void *userData)
+static BaseType_t flexcan_callback(CAN_Type *base, flexcan_handle_t *handle, status_t status, uint32_t result, void *userData)
{
callback_message_t * cb = (callback_message_t*) userData;
BaseType_t reschedule = pdFALSE;
@@ -94,6 +98,7 @@ static void flexcan_callback(CAN_Type *base, flexcan_handle_t *handle, status_t
switch ((int)base)
{
case (int)CAN0:
+
xTaskNotifyFromISR(can_tx_notify_task_handle, 0x01, eSetBits, &reschedule);
break;
case (int)CAN1:
@@ -104,10 +109,40 @@ static void flexcan_callback(CAN_Type *base, flexcan_handle_t *handle, status_t
}
break;
+ case kStatus_FLEXCAN_ErrorStatus:
+ if ((result & (kFLEXCAN_TxWarningIntFlag)) != 0) {
+ switch ((int)base)
+ {
+ case (int)CAN0:
+ registers[APALIS_TK1_K20_CANERR + APALIS_TK1_K20_CAN_DEV_OFFSET(0)] |= EFLG_TXWAR;
+ xTaskNotifyFromISR(can_tx_notify_task_handle, 0x04, eSetBits, &reschedule);
+ break;
+ case (int)CAN1:
+ registers[APALIS_TK1_K20_CANERR + APALIS_TK1_K20_CAN_DEV_OFFSET(1)] |= EFLG_TXWAR;
+ xTaskNotifyFromISR(can_tx_notify_task_handle, 0x08, eSetBits, &reschedule);
+ break;
+ }
+ }
+
+ if ((result & (kFLEXCAN_BusOffIntFlag)) != 0) {
+ switch ((int)base)
+ {
+ case (int)CAN0:
+ registers[APALIS_TK1_K20_CANERR + APALIS_TK1_K20_CAN_DEV_OFFSET(0)] |= EFLG_TXBO;
+ xTaskNotifyFromISR(can_tx_notify_task_handle, 0x04, eSetBits, &reschedule);
+ break;
+ case (int)CAN1:
+ registers[APALIS_TK1_K20_CANERR + APALIS_TK1_K20_CAN_DEV_OFFSET(1)] |= EFLG_TXBO;
+ xTaskNotifyFromISR(can_tx_notify_task_handle, 0x08, eSetBits, &reschedule);
+ break;
+ }
+ }
+ break;
default:
break;
}
- portYIELD_FROM_ISR(reschedule);
+
+ return reschedule;
}
static void CAN_Init(uint8_t id)
@@ -139,7 +174,11 @@ static void CAN_Init(uint8_t id)
FLEXCAN_SetRxFifoConfig(can_regs[id].base, &fifoConfig, true);
/* errata #5641 */
- FLEXCAN_SetTxMbConfig(can_regs[id].base, TX_MESSAGE_BUFFER_NUM0 - 1, true);
+ can_regs[id].base->MB[TX_MESSAGE_BUFFER_NUM0 - 1].ID = 0x0;
+ can_regs[id].base->MB[TX_MESSAGE_BUFFER_NUM0 - 1].WORD0 = 0x0;
+ can_regs[id].base->MB[TX_MESSAGE_BUFFER_NUM0 - 1].WORD1 = 0x0;
+ can_regs[id].base->MB[TX_MESSAGE_BUFFER_NUM0 - 1].CS = CAN_CS_CODE(0x8);
+ can_regs[id].base->MB[TX_MESSAGE_BUFFER_NUM0 - 1].CS = CAN_CS_CODE(0x8);
/* Setup Tx Message Buffer. */
FLEXCAN_SetTxMbConfig(can_regs[id].base, TX_MESSAGE_BUFFER_NUM0, true);
@@ -148,6 +187,7 @@ static void CAN_Init(uint8_t id)
uint8_t available_data[2];
static void can_calculate_available_data(uint8_t id) {
+ taskENTER_CRITICAL();
if ( can_regs[id].rx_buf_bottom <= can_regs[id].rx_buf_top)
available_data[id] = can_regs[id].rx_buf_top - can_regs[id].rx_buf_bottom;
else
@@ -155,13 +195,17 @@ static void can_calculate_available_data(uint8_t id) {
available_data[id] = (available_data[id] > APALIS_TK1_MAX_CAN_DMA_XREF) ? APALIS_TK1_MAX_CAN_DMA_XREF:available_data[id];
registers[APALIS_TK1_K20_CAN_IN_BUF_CNT + APALIS_TK1_K20_CAN_DEV_OFFSET(id)] = available_data[id];
+
if (can_regs[id].rx_buf_bottom == can_regs[id].rx_buf_top)
registers[APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(id)] &= ~CANINTF_RX;
+ else
+ registers[APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(id)] |= CANINTF_RX;
+ taskEXIT_CRITICAL();
}
void can_spi_read_complete(uint8_t id)
{
-
+ can_calculate_available_data(id);
}
static void frame_to_buffer(flexcan_frame_t *frame, uint8_t id) {
@@ -195,24 +239,26 @@ static void frame_to_buffer(flexcan_frame_t *frame, uint8_t id) {
case 2:data_buffer[id][top_frame][5 + 1] = frame->dataByte1;
case 1:data_buffer[id][top_frame][5] = frame->dataByte0;
}
+
can_regs[id].rx_buf_top++;
can_regs[id].rx_buf_top %= CAN_RX_BUF_SIZE;
+
can_calculate_available_data(id);
}
-static void can_fifo_rx(uint8_t id, flexcan_fifo_transfer_t * rxXfer)
+static inline void can_fifo_rx(uint8_t id, flexcan_fifo_transfer_t * rxXfer)
{
callback_message_t *can_msg = (callback_message_t *) can_regs[id].handle.userData;
- taskENTER_CRITICAL();
+
FLEXCAN_TransferReceiveFifoNonBlocking(can_regs[id].base, &can_regs[id].handle, rxXfer);
- taskEXIT_CRITICAL();
xSemaphoreTake(can_msg->sem, portMAX_DELAY);
- frame_to_buffer(rxXfer->frame, id);
- can_regs[id].frames_in_buf++;
- registers[APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(id)] |= CANINTF_RX;
- generate_can_irq(id);
- if (can_regs[id].frames_in_buf >= CAN_RX_BUF_SIZE)
- vTaskSuspend(NULL);
+ if (can_msg->async_status == pdTRUE) {
+ frame_to_buffer(rxXfer->frame, id);
+ can_regs[id].frames_in_buf++;
+ generate_can_irq(id);
+ if (can_regs[id].frames_in_buf >= CAN_RX_BUF_SIZE)
+ vTaskSuspend(NULL);
+ }
}
void can0_task(void *pvParameters) {
@@ -263,16 +309,25 @@ void can1_task(void *pvParameters) {
static void can_change_mode(int id, uint8_t new_mode)
{
- CAN_Type *base = id ? CAN1:CAN0;
-
can_regs[id].can_mode = new_mode;
- switch (new_mode){
- case CAN_CTRLMODE_LOOPBACK:
- base->CTRL1 = base->CTRL1 | CAN_CTRL1_LPB_MASK;
- break;
- case CAN_CTRLMODE_NORMAL:
- base->CTRL1 = base->CTRL1 & ~CAN_CTRL1_LPB_MASK;
+ FLEXCAN_SetMode(can_regs[id].base, new_mode);
+
+}
+
+static void can_enable(int id, uint8_t enable)
+{
+ can_regs[id].can_mode = enable;
+
+ if (enable) {
+ callback_message_t *can_msg = (callback_message_t *) can_regs[id].handle.userData;
+ FLEXCAN_ExitFreezeMode(can_regs[id].base);
+ can_msg->async_status = pdFALSE;
+ xSemaphoreGive(can_msg->sem);
+ generate_can_irq(id);
+ } else {
+ FLEXCAN_TransferAbortReceiveFifo(can_regs[id].base, &can_regs[id].handle);
+ FLEXCAN_EnterFreezeMode(can_regs[id].base);
}
}
@@ -282,18 +337,21 @@ static uint8_t set_canreg (int id, uint8_t value)
registers[APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(id)] = value;
if ( can_regs[id].can_mode != (value & CANCTRL_MODMASK) )
can_change_mode(id, (value & CANCTRL_MODMASK));
+ if (can_regs[id].can_enable != (value & CANCTRL_ENABLE))
+ can_enable(id, (value & CANCTRL_ENABLE));
return 0;
}
static uint8_t clr_canreg (int id, uint8_t mask)
{
- mask &= (CANINTF_TX | CANINTF_ERR);
+ mask &= (CANINTF_RX | CANINTF_TX | CANINTF_ERR);
registers[APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(id)] &= ~mask;
return 0;
}
static uint8_t set_canerr (int id, uint8_t value)
{
+ registers[APALIS_TK1_K20_CANERR + APALIS_TK1_K20_CAN_DEV_OFFSET(id)] = value;
return 0;
}
@@ -304,9 +362,9 @@ static uint8_t set_canbadreg (int id, uint8_t value)
return 0;
}
-static uint8_t set_canbittimig (int id, uint16_t value, int16_t mask)
+static uint8_t set_canbittiming (int id, uint16_t value, int16_t mask)
{
- /* According to NXP we should use default setting */
+ /* According to NXP we should use default settings */
return 0;
}
@@ -339,12 +397,16 @@ uint8_t can_sendframe(uint8_t id, uint8_t *data, uint8_t len)
txXfer.frame = &tx_frame;
txXfer.mbIdx = TX_MESSAGE_BUFFER_NUM0;
-
- taskENTER_CRITICAL();
- FLEXCAN_TransferSendNonBlocking(can_regs[id].base , &can_regs[id].handle, &txXfer);
- taskEXIT_CRITICAL();
-
- return 0;
+ if( tx_frame.length <= 8 ) {
+ FLEXCAN_TransferSendNonBlocking(can_regs[id].base , &can_regs[id].handle, &txXfer);
+ registers[APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(id)] |= CANINTF_TX;
+ return 0;
+ }
+ else {
+ registers[APALIS_TK1_K20_CANREG + APALIS_TK1_K20_CAN_DEV_OFFSET(id)] &= ~CANINTF_TX;
+ generate_can_irq(id);
+ return -EIO;
+ }
}
uint16_t can_readframe(uint8_t id, dspi_transfer_t *spi_transfer)
@@ -354,11 +416,11 @@ uint16_t can_readframe(uint8_t id, dspi_transfer_t *spi_transfer)
rx_size = spi_transfer->rxData[2] / CAN_TRANSFER_BUF_LEN; /* size in frames, not bytes */
if (rx_size > available_data[id])
rx_size = available_data[id];
+
can_regs[id].rx_buf_bottom = can_regs[id].rx_buf_bottom + rx_size;
can_regs[id].rx_buf_bottom %= CAN_RX_BUF_SIZE;
can_regs[id].frames_in_buf -= rx_size;
- can_calculate_available_data(id);
return rx_size * CAN_TRANSFER_BUF_LEN;
}
@@ -378,9 +440,9 @@ int canx_registers(dspi_transfer_t *spi_transfer, int id)
case APALIS_TK1_K20_CAN_BAUD_REG:
return set_canbadreg(id, rx_buf[2]);
case APALIS_TK1_K20_CAN_BIT_1:
- return set_canbittimig(id, rx_buf[2], 0x00FF);
+ return set_canbittiming(id, rx_buf[2], 0x00FF);
case APALIS_TK1_K20_CAN_BIT_2:
- return set_canbittimig(id, (rx_buf[2] << 8), 0xFF00);
+ return set_canbittiming(id, (rx_buf[2] << 8), 0xFF00);
default:
return -EIO;
}
@@ -398,7 +460,7 @@ int canx_registers(dspi_transfer_t *spi_transfer, int id)
switch (rx_buf[1]) {
case APALIS_TK1_K20_CAN_OUT_BUF:
can_sendframe(id, &rx_buf[3], rx_buf[2]);
- break;
+ return 0;
default:
return -EIO;
}