/** * @file sdrv_lin.h * @brief SemiDrive Lin driver header file. * * @copyright Copyright (c) 2020 Semidrive Semiconductor. * All rights reserved. */ #ifndef INCLUDE_DRV_SDRV_LIN_H #define INCLUDE_DRV_SDRV_LIN_H #include #if CONFIG_MAINFUNCTION_ENABLE #include #endif #include #include #include #ifndef ASSEMBLY __BEGIN_CDECLS /* Lin module is half duplex */ #define SDRV_HALF_DUPLEX 1U /* Lin module use software flow control */ #define SDRV_SOFTWARE_FC 1U /* Lin data frame param */ #define SDRV_CHAR_8_BITS 0U #define SDRV_STOP_1_BIT 0U #define SDRV_NO_PARITY 0U /* Lin break is detected as 13 bit time low level on RX/TX line */ #define SDRV_LIN_TXBREAK_LEN (13U) #define SDRV_LIN_RXBREAK_LEN (10U) #define SDRV_LIN_TXBREAK_BIT(bit) (((bit)-8U) + 1U) #define SDRV_LIN_RXBREAK_BIT(bit) (((bit)-9U) + 1U) /* Trigger a transfer by write 0xA53C to register */ #define SDRV_DOORBELL_TRIGGER 0xA53CU /* Abort a transfer by write 0xA53C to register */ #define SDRV_DOORBELL_ABORT 0xA5C3U /* Auto baud detect param */ #define ABR_PATTERN 0U #define SDRV_LIN_ABR_PATTERN_CHAR 0x55U /* Sleep/Wakeup frame id */ #define LIN_SLEEP_ID 0x3cU #define LIN_WAKEUP_ID 0x3dU /* The count of timeout */ #define WaitForever 0xFFFFFFFFU #define NoWait 0x00U #define SDRV_LIN_OPERATION_TIMEOUT 0x200000U /* The mask of timeout value, PCR7-> PCMDTO. */ #define SDRV_LIN_PCR7_PCMDTO_MASK 0x0000001FU /* The mask of id value, PSR4-> LINPID -> ID. */ #define SDRV_LIN_PSR4_LINPID_ID_MASK 0x0000003FU /** @brief Lin interrupt bit mask */ #define SDRV_UART_INTR_TX_FOVF \ (1U << 4) /**< TX fifo overflow interrupt bit mask. */ #define SDRV_UART_INTR_RX_FOVF \ (1U << 5) /**< RX fifo overflow interrupt bit mask. */ #define SDRV_LIN_INTR_PARITYERR \ (1U << 8) /**< Parity error interrupt bitmask. \ */ #define SDRV_LIN_INTR_FRAMEERR \ (1U << 9) /**< Frame error interrupt bitmask. \ */ #define SDRV_LIN_INTR_BAUDRATEERR \ (1U << 10) /**< Baudrate error interrupt bitmask. */ #define SDRV_LIN_INTR_NOISERERR \ (1U << 11) /**< Noise error interrupt bitmask. \ */ #define SDRV_LIN_INTR_ABRPASS \ (1U << 18) /**< Auto baudrate detect pass interrupt bitmask. */ #define SDRV_LIN_INTR_ABRFAIL \ (1U << 19) /**< Auto baudrate detect error interrupt bitmask. */ #define SDRV_LIN_INTR_STARTBITERR \ (1U << 20) /**< Start bit error interrupt bitmask. */ #define SDRV_LIN_INTR_APBCMDDONE \ (1U << 21) /**< APB command completed interrupt bitmask. */ #define SDRV_LIN_INTR_APBCMDABORT \ (1U << 22) /**< APB command abort interrupt bitmask. */ #define SDRV_LIN_INTR_PIDPASS (1U << 23) /**< Receive pid pass*/ #define SDRV_LIN_INTR_PIDERR (1U << 24) /**< Receive pid error*/ #define SDRV_LIN_INTR_RXCHKSUMPASS (1U << 25) /**< Data checksum pass*/ #define SDRV_LIN_INTR_RXCHKSUMERR (1U << 26) /**< Data checksum error*/ /* Sdrv lin frame and fifo error interrupt. */ #define SDEV_LIN_INTR_FRAME_FIFO_ERR \ (SDRV_UART_INTR_TX_FOVF | SDRV_UART_INTR_RX_FOVF | \ SDRV_LIN_INTR_PARITYERR | SDRV_LIN_INTR_FRAMEERR | \ SDRV_LIN_INTR_NOISERERR | SDRV_LIN_INTR_STARTBITERR) /* Sdrv lin abr interrupt. */ #define SDRV_LIN_INTR_ABR (SDRV_LIN_INTR_ABRPASS | SDRV_LIN_INTR_ABRFAIL) /*! * @brief Lin interrupt event type. */ enum lin_interrupt_type { SDRV_LIN_NO_EVENT = 0U, /**< Lin default interrupt state. */ SDRV_LIN_ABR_PASS = 1U, /**< Lin auto baudrate detect pass. */ SDRV_LIN_ABR_FAIL = 2U, /**< Lin auto baudrate detect fail. */ SDRV_LIN_TX_COMPLETE = 3U, /**< Lin transmit completed. */ SDRV_LIN_TX_TIMEOUT = 4U, /**< Lin transmit timeout. */ SDRV_LIN_TX_ERROR = 5U, /**< Lin transmit error. */ SDRV_LIN_RX_COMPLETE = 6U, /**< Lin receive completed. */ SDRV_LIN_RX_TIMEOUT = 7U, /**< Lin receive timeout. */ SDRV_LIN_RX_ERROR = 8U, /**< Lin receive error. */ SDRV_LIN_RX_CHECKSUM_ERR = 9U, /**< Lin receive checksum error. */ SDRV_LIN_RX_PIDPASS = 10U, /**< Lin receive pid success. */ SDRV_LIN_RX_PIDERR = 11U, /**< Lin receive pid error. */ SDRV_LIN_RX_STARTBIT_ERR = 12U, /**< Lin transfer start bit error. */ SDRV_LIN_RX_PARITY_ERR = 13U, /**< Lin receive Parity error. */ SDRV_LIN_RX_FRAME_ERR = 14U, /**< Lin receive frame error. */ SDRV_LIN_RX_BAUDRATE_ERR = 15U, /**< Lin receive baudrate error. */ SDRV_LIN_RX_NOISE_ERR = 16U, /**< Lin receive noise error. */ SDRV_LIN_RX_RXFOVF_ERR = 17U, /**< Lin rx fifo overflow. */ SDRV_LIN_TX_TXFOVF_ERR = 18U, /**< Lin tx fifo overflow.*/ }; typedef struct sdrv_lin sdrv_lin_t; typedef enum lin_interrupt_type lin_interrupt_type_e; /* lin callback function type */ typedef void (*lin_callback_t)(struct sdrv_lin *ctrl, lin_interrupt_type_e linstate, void *userdata); /** * @brief LIN mode. */ typedef enum lin_mode { LIN_MASTER = 1U, /**< Lin module in master mode. */ LIN_SLAVE = 2U, /**< Lin module in slave mode. */ } lin_mode_e; /** * @brief LIN checksum mode. */ typedef enum lin_cs_mode { LIN_CLASSIC_CS = 0U, /* Classic checksum */ LIN_ENHANCED_CS = 1U, /* Enhanced checksum */ } lin_cs_mode_e; /** * @brief LIN Channel status. */ typedef enum lin_ch_status { LIN_CH_UNINITIAL_STATE = 0U, /**< Channel uninitial */ LIN_CH_SLEEP_STATE = 1U, /**< Channel sleep status */ LIN_CH_OPERATIONAL_STATE = 2U, /**< Channel operational */ } lin_ch_status_e; /** * @brief LIN return status. */ typedef enum lin_ret_status { STATUS_SUCCESS = SDRV_STATUS_OK, /**< Status for success. */ STATUS_FAIL = SDRV_STATUS_FAIL, /**< Status for common error*/ STATUS_TIMEOUT = SDRV_STATUS_TIMEOUT, /**< Status for timeout. */ STATUS_BUSY = SDRV_STATUS_BUSY, /**< Status for busy. */ STATUS_INVALID_PARAM = SDRV_STATUS_INVALID_PARAM, /* The param is invalid. */ STATUS_SLEEP = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_LIN, 0U), /**< Module in sleep mode. */ STATUS_UNINIT = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_LIN, 1U), /**< Module should be initialized. */ } lin_ret_status_e; /** * @brief LIN frame status. */ typedef enum lin_sub_status { SDRV_LIN_STATE_IDLE = 0U, /**< RX/TX line idle. */ SDRV_LIN_STATE_BUSY = 1U, /**< RX/TX line busy. */ SDRV_LIN_STATE_TX = 2U, /**< Lin module in transmit mode. */ SDRV_LIN_STATE_TX_ERROR = 3U, /**< Lin transmit error. */ SDRV_LIN_STATE_RX = 4U, /**< Lin module in receive mode. */ SDRV_LIN_STATE_RX_ERROR = 5U, /**< Lin receive error. */ SDRV_LIN_STATE_ABR_READY = 6U, /**< Lin auto baudrate ready. */ SDRV_LIN_STATE_ABR_BUSY = 7U, /**< Lin auto baudrate detecting. */ SDRV_LIN_STATE_ABR_FAIL = 8U, /**< Lin auto baudrate detect fail. */ } lin_sub_status_e; /** * @brief LIN controller struct */ struct sdrv_lin { /* Lin module information. */ uint32_t base; /**< Lin module base. */ int irq; /**< Lin module irq number. */ uint32_t clk_freq; /**< Lin module clock frequency. */ /* Lin channel information. */ uint32_t baud; /**< Lin transfer baudrate. */ lin_mode_e mode; /**< Lin module mode. */ lin_cs_mode_e checksum; /**< Lin transfer checksum type. */ volatile uint8_t current_id; /**< The id of current tranfer. */ volatile lin_interrupt_type_e current_event; volatile lin_ch_status_e channel_sta; /**< Lin channel status. */ lin_callback_t callback; /**< Lin transfer callback function. */ void *userdata; /**< Lin transfer callback function param.*/ volatile uint32_t abr_state; /**< Auto baudrate detect status*/ volatile bool rx_error_invalid; /**< Rx line error is invalid or not after abr. */ /* Lin transfer information. */ const uint8_t *tx_buff; /**< Transmit buffer. */ uint8_t tx_size; /**< Transmit data size . */ volatile uint8_t tx_remain; /**< Transmit remain data size. */ volatile uint32_t tx_state; /**< Transmit state. */ uint8_t *rx_buff; /**< Receive buffer. */ uint8_t rx_size; /**< Receive data size . */ volatile uint8_t rx_remain; /**< Receive remain data size. */ volatile uint32_t rx_state; /**< Receive state. */ #if CONFIG_MAINFUNCTION_ENABLE /* Lin mainfunction information. */ module_mainfunction_t *module_node; /**< The mainfunction node's ptr of this module. */ volatile mainfunction_ret_status_t module_mainfunction_state; /**< The mainfunction state of this module. */ #endif }; /** * @brief LIN controller configure. */ typedef struct sdrv_lin_config { uint32_t base; /**< Lin module base. */ int irq; /**< Lin module irq number. */ uint32_t baud; /**< Lin transfer baudrate. */ uint32_t clk_freq; /**< Lin module clock frequency. */ lin_mode_e mode; /**< Lin module mode. */ lin_cs_mode_e checksum; /**< Lin transfer checksum type. */ /* Auto baudrate detect configurations, these configurations are optional. * Default configuration : Disable auto baudrate detect */ uint8_t abr_en; /**< Auto baudrate detect enable/disable. */ sdrv_abr_max_e match_num; /**< The character number that abr expect to recv and match*/ /* Transfer timeout configurations, these configurations are optional. * If user set transfer_timeout as true, should set timeout_value too. * The range of timeout_value is 0x00 ~ 0x1F. * timeout_value <-> timeout cycle(w_sclk_div) <-> timeout ms(clk 83MHz) * 0x00 2^35 cycle 1/83000000*(2^35) = 413s * 0x01 2^34 cycle 206s * ... ... ... * 0x1F 2^3 cycle 0.1us * * Example/Recommand: * w_sclk_div is 83MHz, 1 cycle is 0.012us. * Baud(bit) <-> timeout_value <-> timeout ms(clk 83MHz) * 1K ~ 2K 0x0B(2^24 cycle) 202ms * 2K ~ 5K 0x0C(2^23 cycle) 101ms * 5k ~ 10k 0x0D(2^22 cycle) 50ms * 10k ~ 15k 0x0E(2^21 cycle) 25ms * 15k ~ 20k 0x0F(2^20 cycle) 12ms */ bool transfer_timeout; /**< Enable/Disable auto detect transfer timeout or not. */ uint8_t timeout_value; /**< Timeout value configuration. */ /* Use mainfunction polling mode to transmit/receive lin frame. * Default configuration is false. */ bool mainfunction_polling; /**< Use mainfunction polling mode or not. */ uint32_t period_ms; /**< The period(ms) of calling module's callback function. */ } sdrv_lin_config_t; typedef struct sdrv_lin_pdu { uint8_t id; /**< The id of current transfer. */ lin_cs_mode_e checksum; /**< The checksum of current transfer. */ uint8_t size; /**< The data size of current transfer. */ uint8_t *data; /**< The data buffer of current transfer. */ } sdrv_lin_pdu_t; /** * @brief LIN controller init. * * This function initializes LIN controller and attach callback function. * Callback fumction is optional. Please input NULL if user do not need * callback function. * * @param[in] ctrl lin controller * @param[in] cfg lin config * @param[in] Callback callback function * @param[in] userdata callback function user param * @return STATUS_SUCCESS : Initializing lin success. * STATUS_TIMEOUT : Reset lin module fail. */ lin_ret_status_e sdrv_lin_controller_init(sdrv_lin_t *ctrl, const sdrv_lin_config_t *cfg, lin_callback_t callback, void *userdata); /** * @brief LIN deinit. * * This function disable the lin module, and change the state of lin channel. * * @param[in] ctrl lin controller */ void sdrv_lin_deinit(sdrv_lin_t *ctrl); /** * @brief Configure lin baud rate. * *This function configures the lin module baud rate. *This function is used to update the lin module baud rate. *after the lin module is initialized by the sdrv_lin_init. * * @param [in] ctrl sdrv lin controller * @param [in] baud baud * @return STATUS_SUCCESS : Setting lin baudrate success. * STATUS_INVALID_PARAM : The param is unvalid. * STATUS_UNINIT : The lin entity is uninitialized. */ lin_ret_status_e sdrv_lin_set_baudrate(sdrv_lin_t *ctrl, uint32_t baud); /** * @brief get lin current id. * *This function get the id of current transfer. *This function is only used in salve mode. * * @param [in] ctrl sdrv lin controller * @return the id of current transfer */ uint8_t sdrv_lin_get_id(sdrv_lin_t *ctrl); /** * @brief LIN transmit frame. * * This function transmit frame with a blocking method. * * @param[in] ctrl lin controller * @param[in] lin_pdu the info of transmit param, include * id: the id of current transfer; * checksum: the checksum of current transfer; * size: the data size of current transfer; * data: the data buffer of current transfer. * @param[in] times timeout count * @return STATUS_SUCCESS : Triger lin transmit process success. * STATUS_UNINIT : The lin entity is uninitialized. * STATUS_SLEEP : The lin entity is sleepy. * STATUS_BUSY : The lin bus is busy. * STATUS_FAIL : The size of frame is bigger than 8. */ lin_ret_status_e sdrv_lin_transmitframe(sdrv_lin_t *ctrl, sdrv_lin_pdu_t *lin_pdu, uint32_t times); /** * @brief Get LIN transmit status. * * This function get status of transmit frame. * * @param[in] ctrl lin controller * @param[in] bytes_remaining the number of bytes that still needed to * transmit * @return STATUS_SUCCESS : Lin transmit the frame success. * STATUS_BUSY : Lin transmit the frame not finished. * STATUS_FAIL : Lin transmit the frame fail. */ lin_ret_status_e sdrv_lin_transmit_status_get(sdrv_lin_t *ctrl, uint8_t *bytes_remaining); /** * @brief LIN get rx fifo data. * * This function receive frame with a blocking method. * * @param[in] ctrl lin controller * @param[in] data the first address of the source buff to received * @param[in] size the size of bytes to receive * @param[in] times the max count of get fifo data * @return STATUS_SUCCESS : Get data from rx fifo success. * STATUS_TIMEOUT : Lin rx fifo is empty until timeout. */ lin_ret_status_e sdrv_lin_get_fifodata(sdrv_lin_t *ctrl, uint8_t *data, size_t size, uint32_t times); /** * @brief LIN receive frame. * * This function receive frame with a blocking method. * * @param[in] ctrl lin controller * @param[in] lin_pdu the info of receive param, include * id: the id of current transfer; * checksum: the checksum of current transfer; * size: the data size of current transfer; * data: the data buffer of current transfer. * @return STATUS_SUCCESS : Triger lin receive process success. * STATUS_UNINIT : The lin entity is uninitialized. * STATUS_SLEEP : The lin entity is sleepy. * STATUS_BUSY : The lin bus is busy. * STATUS_FAIL : The size of frame is bigger than 8. */ lin_ret_status_e sdrv_lin_receiveframe(sdrv_lin_t *ctrl, sdrv_lin_pdu_t *lin_pdu); /** * @brief Get LIN async receive status. * * This function receive frame with a interrupt method. * * @param[in] ctrl lin controller * @param[in] bytes_remaining the number of bytes that still needed to * receive * @return STATUS_SUCCESS : Lin receive the frame success. * STATUS_BUSY : Lin receive the frame not finished. * STATUS_FAIL : Lin receive the frame fail. */ lin_ret_status_e sdrv_lin_receive_status_get(sdrv_lin_t *ctrl, uint8_t *bytes_remaining); /** * @brief Get LIN tranfer status . * * This function check the state of transfer. * * @param[in] ctrl lin controller * @return SDRV_LIN_STATE_IDLE : The lin bus is idle. * SDRV_LIN_STATE_BUSY : The lin bus is busy. */ lin_sub_status_e sdrv_lin_get_transfer_status(sdrv_lin_t *ctrl); /** * @brief Clear LIN tranfer status . * * This function clear the state of transfer. * * @param[in] ctrl lin controller */ void sdrv_lin_clear_transfer_status(sdrv_lin_t *ctrl); /** * @brief Get LIN node status . * * This function check the state of node * * @param[in] ctrl lin controller * @return the state of lin node */ lin_ch_status_e sdrv_lin_get_status(sdrv_lin_t *ctrl); /** * @brief LIN require slave node goto sleep. * * This function send frame require slave node goto sleep. * * @param[in] ctrl lin controller * @return STATUS_SUCCESS : Send sleep frame to slave node success. * STATUS_UNINIT : The lin entity is uninitialized. * STATUS_SLEEP : The lin entity is sleepy. * STATUS_BUSY : The lin bus is busy. * STATUS_FAIL : The size of frame is bigger than 8. */ lin_ret_status_e sdrv_lin_goto_sleep(sdrv_lin_t *ctrl); /** * @brief LIN require this node goto sleep. * * This function send frame require this node goto sleep. * * @param[in] ctrl lin controller * @return STATUS_SUCCESS : Set it's own state to LIN_CH_SLEEP_STATE success. * STATUS_UNINIT : The lin entity is uninitialized. */ lin_ret_status_e sdrv_lin_goto_sleep_internal(sdrv_lin_t *ctrl); /** * @brief LIN remote node wakeup. * * This function wakup the remote node. * * @param[in] ctrl lin controller * @return STATUS_SUCCESS : Send wakeup frame to slave node success. * STATUS_UNINIT : The lin entity is uninitialized. * STATUS_SLEEP : The lin entity is sleepy. * STATUS_BUSY : The lin bus is busy. * STATUS_FAIL : The size of frame is bigger than 8. */ lin_ret_status_e sdrv_lin_wakeup(sdrv_lin_t *ctrl); /** * @brief LIN node wakeup. * * This function wakup this node. * * @param[in] ctrl lin controller * @return STATUS_SUCCESS : Set it's own state to LIN_CH_OPERATIONAL_STATE * success. * STATUS_UNINIT : The lin entity is uninitialized. */ lin_ret_status_e sdrv_lin_wakeup_internal(sdrv_lin_t *ctrl); /** * @brief Enable/Disable Sdrv LIN Interrupt. * * This function enable/disable sdrv lin interrupt with the provided mask. * * @param [in] ctrl sdrv lin controller * @param [in] mask the interrupts to enable * @param [in] value enable or disable */ void sdrv_lin_intr_ctrl(sdrv_lin_t *ctrl, uint32_t mask, bool value); /** * @brief Get Sdrv LIN Interrupt enable/disable status. * * This function get sdrv lin interrupt enable/disable status with the * provided mask. * * @param [in] ctrl sdrv lin controller * @return Sdrv lin Interrupt enable/disable status */ uint32_t sdrv_lin_intr_get(sdrv_lin_t *ctrl); /** * @brief Get Sdrv lin Interrupt flag status. * * This function get Sdrv lin Interrupt flag status. * * @param [in] ctrl sdrv lin controller * @return all sdrv lin Interrupt status */ uint32_t sdrv_lin_intr_status_get(sdrv_lin_t *ctrl); /** * @brief Clear Sdrv lin Interrupt flag status. * * This function clear Sdrv lin Interrupt flag status with the provided mask. * * @param [in] ctrl sdrv lin controller * @param [in] mask the interrupts status to clear */ void sdrv_lin_intr_status_clear(sdrv_lin_t *ctrl, uint32_t mask); /** * @brief Sdrv LIN default IRQ handle function. * * This function handles the sdrv lin transmit and receive * and error IRQ request. * * @param [in] irq the irq number of LINx * @param [in] ctrl sdrv lin controller */ int sdrv_lin_irq_handler(uint32_t irq, void *ctrl); #if CONFIG_MAINFUNCTION_ENABLE /** * @brief Sdrv LIN MainFunction callback function. * * This function handles the transmit/receive/error IRQ of lin module. * * @param [in] ctrl sdrv lin controller */ void sdrv_lin_mainfunction_handler(void *ctrl); #endif __END_CDECLS #endif #endif