Files
test/drivers/include/sdrv_lin.h
2025-11-07 20:19:23 +08:00

580 lines
22 KiB
C

/**
* @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 <compiler.h>
#if CONFIG_MAINFUNCTION_ENABLE
#include <mainfunction/mainfunction.h>
#endif
#include <sdrv_common.h>
#include <sdrv_uart.h>
#include <types.h>
#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