Files
bootloader/validation/embedded_host/MK65F18/src/host_hardware.c
László Monda e6c1fce5b4 Add KBOOT.
2016-08-10 01:45:15 +02:00

890 lines
28 KiB
C

/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "host_hardware.h"
#include "fsl_device_registers.h"
#include "port/fsl_port.h"
#include "flexcan/fsl_flexcan.h"
#include "dspi/fsl_dspi.h"
#include "uart/fsl_uart.h"
#include "i2c/fsl_i2c.h"
#include "utilities/fsl_rtos_abstraction.h"
#include "pin_mux.h"
#include "board.h"
#include "disk.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define k_uartBufferSize 256
#define HOST_UART_INSTANCE 2
/*!
* @brief Internal driver state information.
*
* @note The contents of this structure are internal to the driver and should not be
* modified by users. Also, contents of the structure are subject to change in
* future releases.
*/
typedef struct FlexCANState
{
volatile uint32_t rx_mb_idx; /*!< Index of the message buffer for receiving*/
volatile uint32_t tx_mb_idx; /*!< Index of the message buffer for transmitting*/
semaphore_t txIrqSync; /*!< Used to wait for ISR to complete its TX business.*/
semaphore_t rxIrqSync; /*!< Used to wait for ISR to complete its RX business.*/
} flexcan_state_t;
/*! @brief FlexCAN data info from user*/
typedef struct FlexCANDataInfo
{
flexcan_frame_format_t msg_id_type; /*!< Type of message ID (standard or extended)*/
uint32_t data_length; /*!< Length of Data in Bytes*/
} flexcan_data_info_t;
/*! @brief FlexCAN operation modes*/
typedef enum _flexcan_operation_modes
{
kFlexCanNormalMode, /*!< Normal mode or user mode*/
kFlexCanListenOnlyMode, /*!< Listen-only mode*/
kFlexCanLoopBackMode, /*!< Loop-back mode*/
kFlexCanFreezeMode, /*!< Freeze mode*/
kFlexCanDisableMode, /*!< Module disable mode*/
} flexcan_operation_modes_t;
/*!
* @brief flexCAN common information structure
*/
typedef struct _flexcan_transfer_info
{
flexcan_state_t state; //!< state
flexcan_data_info_t rx_info; //!< tx info
flexcan_data_info_t tx_info; //!< tx info
uint32_t rxId; //!< rx id
uint32_t txId; //!< tx id
uint32_t rx_mailbox_num; //!< rx mb number
uint32_t tx_mailbox_num; //!< tx mb number
uint8_t rx_buf[64]; //!< rx buffer
uint8_t rx_buf_write_index; //!< rx buffer write index
uint8_t rx_buf_read_index; //!< rx buffer read index
} flexcan_transfer_info_t;
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief uart byte receive callback.
*/
static void s_uart_byte_receive_callback(uint8_t byte);
/*!
* @brief I2C transfer callback.
*/
static void i2c_master_callback(I2C_Type *base, i2c_master_handle_t *handle, status_t status, void *userData);
/*!
* @brief Return specified UART clock, LPUART0 is not supported here.
*/
static uint32_t get_uart_clock(uint32_t instance);
/*! @brief init uart functions. */
static void init_suarts(void);
/*! @brief dspi initialization. */
static void init_dspi(void);
/*! @brief i2c initialization. */
static void init_i2c(uint32_t instance);
/*! @brief flexcan initialization. */
static void init_flexcan(void);
static void read_can_data(uint8_t data, uint32_t instance);
static status_t FLEXCAN_Send(uint8_t instance,
uint32_t mb_idx,
flexcan_data_info_t *tx_info,
uint32_t msg_id,
uint8_t *mb_data,
uint32_t timeout_ms);
//! @brief flexCAN reset buffer process
static void reset_can_buffer(void);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Variable for DSPI setup information */
static dspi_master_config_t g_dspiConfig;
static dspi_transfer_t g_dspi_masterXfer;
const static uint32_t g_dspiBaseAddr[] = SPI_BASE_ADDRS;
dspi_master_handle_t g_dspi_masterHandle;
/*! @brief Variable for I2C setup information */
static i2c_master_config_t s_i2cMasterConfig;
static i2c_master_transfer_t s_i2c_masterXfer;
const static uint32_t g_i2cBaseAddr[] = I2C_BASE_ADDRS;
i2c_master_handle_t g_i2c_masterHandle = { 0 };
volatile bool g_I2C_MasterCompletionFlag = false;
/* Uart1 */
static uint8_t *s_uart_rxData;
static uint32_t s_uart_bytesRx;
/* Uart1 buffer */
static uint8_t s_uartBuffer[k_uartBufferSize];
static uint8_t *s_uartPtr = s_uartBuffer;
static uint32_t s_uartBufferOffset = 0;
/* Array of UART peripheral base address. */
static UART_Type *const s_uartBase[] = UART_BASE_PTRS;
/* Array of UART IRQ number. */
static const IRQn_Type s_uartIRQ[] = UART_RX_TX_IRQS;
/* FlexCan */
const static uint32_t g_flexcanBaseAddr[] = CAN_BASE_ADDRS;
/* Tables to save CAN IRQ enum numbers defined in CMSIS header file. */
const IRQn_Type g_flexcanRxWarningIrqId[] = CAN_Rx_Warning_IRQS;
const IRQn_Type g_flexcanTxWarningIrqId[] = CAN_Tx_Warning_IRQS;
const IRQn_Type g_flexcanWakeUpIrqId[] = CAN_Wake_Up_IRQS;
const IRQn_Type g_flexcanErrorIrqId[] = CAN_Error_IRQS;
const IRQn_Type g_flexcanBusOffIrqId[] = CAN_Bus_Off_IRQS;
const IRQn_Type g_flexcanOredMessageBufferIrqId[] = CAN_ORed_Message_buffer_IRQS;
/*!
* @brief flexCAN timing table (120Mhz)contains propseg, pseg1, pseg2, pre_divider, rjw
*/
flexcan_timing_config_t bit_rate_table[] = {
{ 47, 1, 3, 2, 1 }, /* 125 kHz */
{ 23, 1, 3, 2, 1 }, /* 250 kHz */
{ 11, 1, 3, 2, 1 }, /* 500 kHz */
{ 7, 1, 3, 2, 1 }, /* 750 kHz */
{ 5, 1, 3, 2, 1 }, /* 1 MHz */
};
/*!
* @brief flexCAN instance used for bus pal
*/
uint8_t flexcanInstance = 0;
//! @brief Global state for the FlexCAN peripheral interface.
flexcan_transfer_info_t s_flexcanInfo;
/*******************************************************************************
* Code
******************************************************************************/
void hardware_init(void)
{
uint32_t count = 0;
uint32_t regPrimask = 0U;
/* Disable the MPU otherwise USB cannot access the bus */
MPU->CESR = 0;
BOARD_InitPins();
BOARD_InitLED();
BOARD_InitSwitch();
microseconds_init();
init_suarts();
init_dspi();
init_flexcan();
init_i2c(I2C_INSTANCE);
/* Wait to hardware stable */
microseconds_delay(500000);
microseconds_shutdown();
for (uint32_t i = 0; i < 100; i++)
{
if (BOARD_ReadSwitch(kSwitch3))
{
count++;
}
}
if (count > 60)
{
disk_init();
FLASH_Init(&s_flashInstance);
/* Disable IRQ, protect ring buffer. */
regPrimask = __get_PRIMASK();
__disable_irq();
/* 1M flash region to store flash image */
FLASH_Erase(&s_flashInstance, MSD_FLASH_BASE, 1024 * 1024, kFLASH_ApiEraseKey);
/* Recover PRIMASK, enable IRQ if previously enabled. */
__set_PRIMASK(regPrimask);
}
PORT_SetPinInterruptConfig(BOARD_SW2_PORT, BOARD_SW2_GPIO_PIN, kPORT_InterruptFallingEdge);
EnableIRQ(BOARD_SW2_IRQ);
PORT_SetPinInterruptConfig(BOARD_SW3_PORT, BOARD_SW3_GPIO_PIN, kPORT_InterruptFallingEdge);
EnableIRQ(BOARD_SW3_IRQ);
}
uint32_t get_bus_clock(void)
{
uint32_t busClockDivider = ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV2_MASK) >> SIM_CLKDIV1_OUTDIV2_SHIFT) + 1;
return (SystemCoreClock / busClockDivider);
}
uint32_t get_fast_peripheral_clock(void)
{
uint32_t busClockDivider = ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV2_MASK) >> SIM_CLKDIV1_OUTDIV2_SHIFT) + 1;
return (SystemCoreClock / busClockDivider);
}
bool usb_clock_init(void)
{
SIM->CLKDIV2 = (uint32_t)0x0UL; /* Update USB clock prescalers */
/* Select MCGPLLCLK clock */
SIM->SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK;
SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL(0x01U));
SIM->CLKDIV2 = (uint32_t)0x09UL; /* Update USB clock prescalers */
/* Enable USB-OTG IP clocking */
SIM->SCGC4 |= (SIM_SCGC4_USBOTG_MASK);
/* Configure enable USB regulator for device */
SIM->SOPT1 |= SIM_SOPT1_USBREGEN_MASK;
/* SIM_SOPT1: OSC32KSEL=0 */
SIM->SOPT1 &=
(uint32_t)~SIM_SOPT1_OSC32KSEL_MASK; /* System oscillator drives 32 kHz clock for various peripherals */
return true;
}
static void init_suarts(void)
{
/* UART2 for OpenSDA and UART4 for Kibble */
uart_config_t config;
UART_GetDefaultConfig(&config);
config.baudRate_Bps = kUART_DEFAULT_BAUD;
config.enableTx = true;
config.enableRx = true;
UART_Init(s_uartBase[HOST_UART_INSTANCE], &config, get_uart_clock(HOST_UART_INSTANCE));
EnableIRQ(s_uartIRQ[UART_INSTANCE]);
UART_Init(s_uartBase[UART_INSTANCE], &config, get_uart_clock(UART_INSTANCE));
UART_EnableInterrupts(s_uartBase[UART_INSTANCE], kUART_RxDataRegFullInterruptEnable);
}
static uint32_t get_uart_clock(uint32_t instance)
{
switch (instance)
{
case 0:
case 1:
/* UART0 and UART1 always use the system clock */
return SystemCoreClock;
case 2:
return get_bus_clock();
case 3:
case 4:
/* UART2-4 always use the bus clock. */
return get_bus_clock();
default:
return 0;
}
}
static void init_dspi(void)
{
uint32_t baseAddr = g_dspiBaseAddr[SPI_INSTANCE];
DSPI_MasterGetDefaultConfig(&g_dspiConfig);
g_dspiConfig.whichCtar = kDSPI_Ctar1;
g_dspiConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveLow;
g_dspiConfig.ctarConfig.cpha = kDSPI_ClockPhaseSecondEdge;
g_dspiConfig.ctarConfig.baudRate = 100000U;
DSPI_MasterInit((SPI_Type *)baseAddr, &g_dspiConfig, get_bus_clock());
g_dspi_masterXfer.configFlags = kDSPI_MasterCtar1 | kDSPI_MasterPcs0 | kDSPI_MasterPcsContinuous;
}
static void init_i2c(uint32_t instance)
{
I2C_MasterGetDefaultConfig(&s_i2cMasterConfig);
I2C_MasterInit((I2C_Type *)g_i2cBaseAddr[instance], &s_i2cMasterConfig, get_bus_clock());
I2C_MasterTransferCreateHandle((I2C_Type *)g_i2cBaseAddr[instance], &g_i2c_masterHandle, i2c_master_callback, NULL);
s_i2c_masterXfer.slaveAddress = 0x10;
s_i2c_masterXfer.subaddress = 0;
s_i2c_masterXfer.subaddressSize = 0;
s_i2c_masterXfer.flags = kI2C_TransferDefaultFlag;
}
static void init_flexcan(void)
{
flexcan_config_t config;
uint32_t baseAddr = g_flexcanBaseAddr[FLEXCAN_INSTANCE];
FLEXCAN_GetDefaultConfig(&config);
config.clkSrc = kFLEXCAN_ClkSrcPeri;
config.baudRate = 125000;
/* Select mailbox number */
s_flexcanInfo.rx_mailbox_num = 8;
s_flexcanInfo.tx_mailbox_num = 9;
/* make bootloader as node 'b' for testing */
s_flexcanInfo.rxId = 0x123;
s_flexcanInfo.txId = 0x321;
s_flexcanInfo.rx_buf_write_index = 0;
s_flexcanInfo.rx_buf_read_index = 0;
/* Init the interrupt sync object.*/
OSA_SemaCreate(&s_flexcanInfo.state.txIrqSync, 0);
OSA_SemaCreate(&s_flexcanInfo.state.rxIrqSync, 0);
s_flexcanInfo.state.rx_mb_idx = 8;
s_flexcanInfo.state.tx_mb_idx = 9;
/* also need to get clock selection config data */
FLEXCAN_Init((CAN_Type *)baseAddr, &config, get_bus_clock());
FLEXCAN_Enable((CAN_Type *)baseAddr, true);
FLEXCAN_EnableInterrupts((CAN_Type *)baseAddr, kFLEXCAN_ErrorInterruptEnable);
/* using setting table */
FLEXCAN_SetTimingConfig((CAN_Type *)baseAddr, &bit_rate_table[0]);
/* FlexCAN reveive config */
s_flexcanInfo.rx_info.msg_id_type = kFLEXCAN_FrameFormatStandard;
s_flexcanInfo.rx_info.data_length = 8;
/* Configure RX MB fields */
flexcan_rx_mb_config_t mbConfig;
mbConfig.format = kFLEXCAN_FrameFormatStandard;
mbConfig.id = CAN_ID_STD(s_flexcanInfo.rxId);
mbConfig.type = kFLEXCAN_FrameTypeData;
FLEXCAN_SetRxMbConfig((CAN_Type *)baseAddr, 8, &mbConfig, true);
FLEXCAN_EnableMbInterrupts((CAN_Type *)baseAddr, 1 << 8);
/* FlexCAN transfer config */
s_flexcanInfo.tx_info.msg_id_type = kFLEXCAN_FrameFormatStandard;
s_flexcanInfo.tx_info.data_length = 8;
FLEXCAN_SetTxMbConfig((CAN_Type *)baseAddr, 9, false);
NVIC_EnableIRQ(g_flexcanErrorIrqId[FLEXCAN_INSTANCE]);
NVIC_EnableIRQ(g_flexcanBusOffIrqId[FLEXCAN_INSTANCE]);
NVIC_EnableIRQ(g_flexcanOredMessageBufferIrqId[FLEXCAN_INSTANCE]);
}
bool wait_uart_char(uint8_t *data)
{
/* If has data */
if (s_uartBase[HOST_UART_INSTANCE]->RCFIFO)
{
*data = UART_ReadByte(s_uartBase[HOST_UART_INSTANCE]);
return true;
}
else
{
return false;
}
}
uint8_t wait_uart_char_blocking(void)
{
uint8_t byte = 0;
UART_ReadBlocking(s_uartBase[HOST_UART_INSTANCE], &byte, 1);
return byte;
}
void configure_spi_speed(uint32_t speedkhz)
{
uint32_t bitsPerSec = speedkhz * 1000;
DSPI_MasterSetBaudRate((SPI_Type *)g_dspiBaseAddr[SPI_INSTANCE], kDSPI_Ctar1, bitsPerSec, get_bus_clock());
}
status_t send_spi_data(uint8_t *src, uint32_t writeLength)
{
g_dspi_masterXfer.txData = src;
g_dspi_masterXfer.rxData = NULL;
g_dspi_masterXfer.dataSize = writeLength;
DSPI_MasterTransferBlocking((SPI_Type *)g_dspiBaseAddr[SPI_INSTANCE], &g_dspi_masterXfer);
return kStatus_Success;
}
status_t receive_spi_data(uint8_t *dest, uint32_t readLength)
{
g_dspi_masterXfer.txData = NULL;
g_dspi_masterXfer.rxData = dest;
g_dspi_masterXfer.dataSize = readLength;
DSPI_MasterTransferBlocking((SPI_Type *)g_dspiBaseAddr[SPI_INSTANCE], &g_dspi_masterXfer);
return kStatus_Success;
}
void configure_i2c_speed(uint32_t speedkhz)
{
I2C_MasterSetBaudRate((I2C_Type *)g_i2cBaseAddr[I2C_INSTANCE], speedkhz * 1000, get_bus_clock());
}
status_t send_i2c_data(uint8_t *src, uint32_t writeLength)
{
s_i2c_masterXfer.direction = kI2C_Write;
s_i2c_masterXfer.data = src;
s_i2c_masterXfer.dataSize = writeLength;
I2C_MasterTransferBlocking((I2C_Type *)g_i2cBaseAddr[I2C_INSTANCE], &s_i2c_masterXfer);
return kStatus_Success;
}
static void i2c_master_callback(I2C_Type *base, i2c_master_handle_t *handle, status_t status, void *userData)
{
/* Signal transfer success when received success status. */
if (status == kStatus_Success)
{
g_I2C_MasterCompletionFlag = true;
}
}
status_t receive_i2c_data(uint8_t *dest, uint32_t readLength)
{
uint16_t timeout = UINT16_MAX;
s_i2c_masterXfer.direction = kI2C_Read;
s_i2c_masterXfer.data = dest;
s_i2c_masterXfer.dataSize = readLength;
I2C_MasterTransferNonBlocking((I2C_Type *)g_i2cBaseAddr[I2C_INSTANCE], &g_i2c_masterHandle, &s_i2c_masterXfer);
/* Reset master completion flag to false. */
g_I2C_MasterCompletionFlag = false;
/* Wait for transfer completed. */
while ((!g_I2C_MasterCompletionFlag) && (--timeout))
{
}
if (timeout == 0)
{
return kStatus_Timeout;
}
g_I2C_MasterCompletionFlag = false;
return kStatus_Success;
}
void configure_can_speed(uint32_t speedkhz)
{
/* Just support 125K, 250K, 500K, 750K, and 1000K */
uint32_t speed_index = 0;
switch (speedkhz)
{
case kFLEXCAN_125K:
speed_index = 0;
break;
case kFLEXCAN_250K:
speed_index = 1;
break;
case kFLEXCAN_500K:
speed_index = 2;
break;
case kFLEXCAN_750K:
speed_index = 3;
break;
case kFLEXCAN_1000K:
speed_index = 4;
break;
}
if (speed_index < 5)
{
/* using setting table */
FLEXCAN_SetTimingConfig((CAN_Type *)g_flexcanBaseAddr[FLEXCAN_INSTANCE], &bit_rate_table[speed_index]);
}
}
status_t send_can_data(uint8_t *src, uint32_t writeLength)
{
uint32_t sentCnt = 0;
uint8_t *sendPtr = src;
while (sentCnt < writeLength)
{
if ((writeLength - sentCnt) <= 8)
{
/* number of bytes to be sent */
s_flexcanInfo.tx_info.data_length = writeLength - sentCnt;
sentCnt += writeLength - sentCnt;
}
else
{
/* number of bytes to be sent */
s_flexcanInfo.tx_info.data_length = 8;
sentCnt += 8;
}
FLEXCAN_Send(FLEXCAN_INSTANCE, 9, &s_flexcanInfo.tx_info, s_flexcanInfo.txId, (uint8_t *)sendPtr, 1000);
sendPtr += s_flexcanInfo.tx_info.data_length;
}
reset_can_buffer();
return kStatus_Success;
}
status_t FLEXCAN_Send(uint8_t instance,
uint32_t mb_idx,
flexcan_data_info_t *tx_info,
uint32_t msg_id,
uint8_t *mb_data,
uint32_t timeout_ms)
{
uint32_t baseAddr = g_flexcanBaseAddr[instance];
osa_status_t syncStatus;
uint8_t i;
flexcan_frame_t frame;
flexcan_mb_transfer_t xfer;
xfer.mbIdx = mb_idx;
frame.format = tx_info->msg_id_type;
frame.length = tx_info->data_length;
frame.id = CAN_ID_STD(msg_id);
frame.type = kFLEXCAN_FrameTypeData;
xfer.frame = &frame;
/* Copy user's buffer into the message buffer data area*/
if (mb_data != NULL)
{
xfer.frame->dataWord0 = 0x0;
xfer.frame->dataWord1 = 0x0;
for (i = 0; i < tx_info->data_length; i++)
{
uint32_t temp, temp1;
temp1 = (*(mb_data + i));
if (i < 4)
{
temp = temp1 << ((3 - i) * 8);
xfer.frame->dataWord0 |= temp;
}
else
{
temp = temp1 << ((7 - i) * 8);
xfer.frame->dataWord1 |= temp;
}
}
}
if (kStatus_Success == FLEXCAN_WriteTxMb((CAN_Type *)baseAddr, mb_idx, xfer.frame))
{
/* Enable Message Buffer Interrupt. */
FLEXCAN_EnableMbInterrupts((CAN_Type *)baseAddr, 1 << mb_idx);
do
{
syncStatus = OSA_SemaWait(&s_flexcanInfo.state.txIrqSync, timeout_ms);
} while (syncStatus == kStatus_OSA_Idle);
/* Disable message buffer interrupt*/
FLEXCAN_DisableMbInterrupts((CAN_Type *)baseAddr, 1 << mb_idx);
/* Wait for the interrupt*/
if (syncStatus != kStatus_OSA_Success)
{
return kStatus_Timeout;
}
else
{
return kStatus_Success;
}
}
else
{
return kStatus_Fail;
}
}
void FLEXCAN_IRQHandler(uint8_t instance)
{
volatile uint32_t flag_reg;
uint32_t temp;
CAN_Type *baseAddr = (CAN_Type *)g_flexcanBaseAddr[instance];
/* Get the interrupts that are enabled and ready */
flag_reg = (baseAddr->IFLAG1 & baseAddr->IMASK1);
/* Check Tx/Rx interrupt flag and clear the interrupt */
if (flag_reg)
{
temp = (1 << s_flexcanInfo.state.rx_mb_idx);
if (flag_reg & temp)
{
OSA_SemaPost(&s_flexcanInfo.state.rxIrqSync);
flexcan_frame_t rxFrame;
/* Get RX MB field values*/
if (!FLEXCAN_ReadRxMb(baseAddr, s_flexcanInfo.state.rx_mb_idx, &rxFrame))
{
uint8_t i;
uint8_t sink_byte = 0;
for (i = 0; i < rxFrame.length; i++)
{
switch (i)
{
case 0:
sink_byte = rxFrame.dataByte0;
break;
case 1:
sink_byte = rxFrame.dataByte1;
break;
case 2:
sink_byte = rxFrame.dataByte2;
break;
case 3:
sink_byte = rxFrame.dataByte3;
break;
case 4:
sink_byte = rxFrame.dataByte4;
break;
case 5:
sink_byte = rxFrame.dataByte5;
break;
case 6:
sink_byte = rxFrame.dataByte6;
break;
case 7:
sink_byte = rxFrame.dataByte7;
break;
default:
break;
}
read_can_data(sink_byte, instance);
}
}
}
temp = (1 << s_flexcanInfo.state.tx_mb_idx);
if (flag_reg & temp)
{
OSA_SemaPost(&s_flexcanInfo.state.txIrqSync);
}
baseAddr->IFLAG1 = flag_reg;
}
/* Clear all other interrupts in ERRSTAT register (Error, Busoff, Wakeup) */
FLEXCAN_ClearStatusFlags(baseAddr, kFLEXCAN_ErrorFlag | CAN_ESR1_ERRINT_MASK);
return;
}
/*FUNCTION**********************************************************************
*
* Function Name : FLEXCAN_IRQBusoffHandler
* Description : Busoff interrupt handler
*
*END**************************************************************************/
void FLEXCAN_IRQBusoffHandler(uint8_t instance)
{
uint32_t baseAddr = g_flexcanBaseAddr[instance];
FLEXCAN_ClearStatusFlags((CAN_Type *)baseAddr, kFLEXCAN_ErrorFlag | CAN_ESR1_ERRINT_MASK);
}
/*FUNCTION**********************************************************************
*
* Function Name : FLEXCAN_DRV_IRQ_Error_Handler
* Description : flexCAN general error interrupt handler
*
*END**************************************************************************/
void FLEXCAN_IRQErrorHandler(uint8_t instance)
{
uint32_t baseAddr = g_flexcanBaseAddr[instance];
FLEXCAN_ClearStatusFlags((CAN_Type *)baseAddr, kFLEXCAN_ErrorFlag | CAN_ESR1_ERRINT_MASK);
}
/*FUNCTION**********************************************************************
*
* Function Name : receive_can_data
* Description : flexCAN receiving data process
*
*END**************************************************************************/
static void read_can_data(uint8_t data, uint32_t instance)
{
s_flexcanInfo.rx_buf[s_flexcanInfo.rx_buf_write_index++] = data;
s_flexcanInfo.rx_buf_write_index &= 0x3f;
}
/*FUNCTION**********************************************************************
*
* Function Name : reset_can_buffer
* Description : flexCAN reset buffer process
*
*END**************************************************************************/
static void reset_can_buffer(void)
{
s_flexcanInfo.rx_buf_write_index = 0;
s_flexcanInfo.rx_buf_read_index = 0;
}
/*FUNCTION**********************************************************************
*
* Function Name : read_can_data
* Description : flexCAN read data process
*
*END**************************************************************************/
status_t receive_can_data(uint8_t *dest, uint32_t readLength)
{
uint8_t received_cnt = 0;
uint16_t timeout = UINT16_MAX;
while ((received_cnt < readLength) && (--timeout))
{
if (s_flexcanInfo.rx_buf_read_index != s_flexcanInfo.rx_buf_write_index)
{
dest[received_cnt++] = s_flexcanInfo.rx_buf[s_flexcanInfo.rx_buf_read_index++];
s_flexcanInfo.rx_buf_read_index &= 0x3f;
}
}
if (timeout == 0)
{
init_flexcan();
return kStatus_Timeout;
}
return kStatus_Success;
}
void configure_uart_speed(uint32_t baud)
{
uart_config_t config;
UART_GetDefaultConfig(&config);
config.baudRate_Bps = baud;
config.enableTx = true;
config.enableRx = true;
UART_Init(s_uartBase[UART_INSTANCE], &config, get_bus_clock());
}
status_t send_uart_data(uint8_t *src, uint32_t writeLength)
{
UART_WriteBlocking(s_uartBase[UART_INSTANCE], src, writeLength);
return kStatus_Success;
}
status_t receive_uart_data(uint8_t *dest, uint32_t readLength)
{
uint16_t timeout = UINT16_MAX;
while ((((s_uart_bytesRx + k_uartBufferSize - s_uartBufferOffset) % k_uartBufferSize) < readLength) && (--timeout))
{
}
if (timeout == 0)
{
return kStatus_Timeout;
}
for (uint32_t i = 0; i < readLength; i++)
{
dest[i] = s_uartPtr[(s_uartBufferOffset + i) % k_uartBufferSize];
}
s_uartBufferOffset = (s_uartBufferOffset + sizeof(uint8_t) * readLength) % k_uartBufferSize;
return kStatus_Success;
}
void UART4_RX_TX_IRQHandler(void)
{
if (UART4->S1 & UART_S1_RDRF_MASK)
{
s_uart_byte_receive_callback(UART4->D);
}
}
static void s_uart_byte_receive_callback(uint8_t byte)
{
s_uart_rxData = s_uartPtr;
if (s_uart_rxData)
{
s_uart_rxData[s_uart_bytesRx] = byte;
s_uart_bytesRx = (s_uart_bytesRx + 1) % k_uartBufferSize;
}
s_uart_rxData = 0;
}
void CAN0_ORed_Message_buffer_IRQHandler(void)
{
FLEXCAN_IRQHandler(0);
}
/* Implementation of CAN0 handler named in startup code. */
void CAN0_Bus_Off_IRQHandler(void)
{
FLEXCAN_IRQBusoffHandler(0);
}
/* Implementation of CAN0 handler named in startup code. */
void CAN0_Error_IRQHandler(void)
{
FLEXCAN_IRQErrorHandler(0);
}
void CAN0_Wake_Up_IRQHandler(void)
{
FLEXCAN_IRQHandler(0);
}
#if __ICCARM__
size_t __write(int handle, const unsigned char *buf, size_t size)
{
while (size--)
{
UART_WriteBlocking(s_uartBase[HOST_UART_INSTANCE], (uint8_t const *)buf++, 1);
}
return size;
}
#endif /* __ICCARM__ */