1149 lines
36 KiB
C
1149 lines
36 KiB
C
/**
|
|
**************************************************************************
|
|
* @file at32f435_437_can.c
|
|
* @version v2.0.9
|
|
* @date 2022-06-28
|
|
* @brief contains all the functions for the can firmware library
|
|
**************************************************************************
|
|
* Copyright notice & Disclaimer
|
|
*
|
|
* The software Board Support Package (BSP) that is made available to
|
|
* download from Artery official website is the copyrighted work of Artery.
|
|
* Artery authorizes customers to use, copy, and distribute the BSP
|
|
* software and its related documentation for the purpose of design and
|
|
* development in conjunction with Artery microcontrollers. Use of the
|
|
* software is governed by this copyright notice and the following disclaimer.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
|
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
|
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
|
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
|
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
|
*
|
|
**************************************************************************
|
|
*/
|
|
|
|
#include "at32f435_437_conf.h"
|
|
|
|
/** @addtogroup AT32F435_437_periph_driver
|
|
* @{
|
|
*/
|
|
|
|
/** @defgroup CAN
|
|
* @brief CAN driver modules
|
|
* @{
|
|
*/
|
|
|
|
#ifdef CAN_MODULE_ENABLED
|
|
|
|
/** @defgroup CAN_private_functions
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @brief deinitialize the can peripheral registers to their default reset values.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @retval none.
|
|
*/
|
|
void can_reset(can_type* can_x)
|
|
{
|
|
if(can_x == CAN1)
|
|
{
|
|
crm_periph_reset(CRM_CAN1_PERIPH_RESET, TRUE);
|
|
crm_periph_reset(CRM_CAN1_PERIPH_RESET, FALSE);
|
|
}
|
|
else if(can_x == CAN2)
|
|
{
|
|
crm_periph_reset(CRM_CAN2_PERIPH_RESET, TRUE);
|
|
crm_periph_reset(CRM_CAN2_PERIPH_RESET, FALSE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief fill each can_baudrate_struct member with its default value.
|
|
* @param can_baudrate_struct: pointer to a can_baudrate_type structure which will be initialized.
|
|
* @retval none.
|
|
*/
|
|
void can_baudrate_default_para_init(can_baudrate_type* can_baudrate_struct)
|
|
{
|
|
/* reset can baudrate structure parameters values */
|
|
|
|
/* baud rate division */
|
|
can_baudrate_struct->baudrate_div = 1;
|
|
|
|
/* resynchronization adjust width */
|
|
can_baudrate_struct->rsaw_size = CAN_RSAW_2TQ;
|
|
|
|
/* bit time segment 1 */
|
|
can_baudrate_struct->bts1_size = CAN_BTS1_4TQ;
|
|
|
|
/* bit time segment 2 */
|
|
can_baudrate_struct->bts2_size = CAN_BTS2_3TQ;
|
|
}
|
|
|
|
/**
|
|
* @brief set the baudrate of the can peripheral
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @param can_baudrate_struct: pointer to a can_baudrate_type structure which will be set.
|
|
* @note baudrate calculate method is:
|
|
* baudrate = fpclk/(baudrate_div *(3 + bts1_size + bts2_size))
|
|
* @retval the result of baudrate set
|
|
* this parameter can be one of the following values:
|
|
* SUCCESS or ERROR
|
|
*/
|
|
error_status can_baudrate_set(can_type* can_x, can_baudrate_type* can_baudrate_struct)
|
|
{
|
|
error_status status_index = ERROR;
|
|
uint32_t wait_ack_index = 0x00000000;
|
|
/* exit from doze mode */
|
|
can_x->mctrl_bit.dzen = FALSE;
|
|
|
|
/* request freeze mode */
|
|
can_x->mctrl_bit.fzen = TRUE;
|
|
|
|
/* wait the acknowledge */
|
|
while((!can_x->msts_bit.fzc) && (wait_ack_index != FZC_TIMEOUT))
|
|
{
|
|
wait_ack_index++;
|
|
}
|
|
|
|
/* check acknowledge */
|
|
if(can_x->msts_bit.fzc)
|
|
{
|
|
can_x->btmg_bit.brdiv = can_baudrate_struct->baudrate_div - 1;
|
|
can_x->btmg_bit.rsaw = can_baudrate_struct->rsaw_size;
|
|
can_x->btmg_bit.bts1 = can_baudrate_struct->bts1_size;
|
|
can_x->btmg_bit.bts2 = can_baudrate_struct->bts2_size;
|
|
|
|
/* request leave freeze mode */
|
|
can_x->mctrl_bit.fzen = FALSE;
|
|
|
|
/* wait the acknowledge */
|
|
wait_ack_index = 0;
|
|
while((can_x->msts_bit.fzc) && (wait_ack_index != FZC_TIMEOUT))
|
|
{
|
|
wait_ack_index++;
|
|
}
|
|
|
|
/* check acknowledged */
|
|
if(can_x->msts_bit.fzc)
|
|
{
|
|
status_index = ERROR;
|
|
}
|
|
else
|
|
{
|
|
status_index = SUCCESS ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
status_index = ERROR;
|
|
}
|
|
|
|
/* return the status of baudrate set */
|
|
return status_index;
|
|
}
|
|
|
|
/**
|
|
* @brief fill each can_init_struct member with its default value.
|
|
* @param can_base_struct: pointer to a can_base_type structure which will be initialized.
|
|
* @retval none.
|
|
*/
|
|
void can_default_para_init(can_base_type* can_base_struct)
|
|
{
|
|
/* reset can init structure parameters values */
|
|
|
|
/* initialize the time triggered communication mode */
|
|
can_base_struct->ttc_enable = FALSE;
|
|
|
|
/* initialize the automatic exit bus-off management */
|
|
can_base_struct->aebo_enable = FALSE;
|
|
|
|
/* initialize the automatic exit doze mode */
|
|
can_base_struct->aed_enable = FALSE;
|
|
|
|
/* initialize the prohibit retransmission when sending fails */
|
|
can_base_struct->prsf_enable = FALSE;
|
|
|
|
/* initialize the message discarding rule select when overflow */
|
|
can_base_struct->mdrsel_selection = CAN_DISCARDING_FIRST_RECEIVED;
|
|
|
|
/* initialize the multiple message sending sequence rule */
|
|
can_base_struct->mmssr_selection = CAN_SENDING_BY_ID;
|
|
|
|
/* initialize the can_mode */
|
|
can_base_struct->mode_selection = CAN_MODE_COMMUNICATE;
|
|
}
|
|
|
|
/**
|
|
* @brief initialize the can peripheral according to the specified
|
|
* parameters in the can_init_struct.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @param can_base_struct: pointer to a can_base_struct structure that contains the configuration information for the can peripheral.
|
|
* @retval the status of initialization
|
|
* this parameter can be one of the following values:
|
|
* SUCCESS or ERROR
|
|
*/
|
|
error_status can_base_init(can_type* can_x, can_base_type* can_base_struct)
|
|
{
|
|
error_status init_status_index = ERROR;
|
|
uint32_t wait_ack_index = 0x00000000;
|
|
/* exit from doze mode */
|
|
can_x->mctrl_bit.dzen = FALSE;
|
|
|
|
/* request freeze mode */
|
|
can_x->mctrl_bit.fzen = TRUE;
|
|
|
|
/* wait the acknowledge */
|
|
while((!can_x->msts_bit.fzc) && (wait_ack_index != FZC_TIMEOUT))
|
|
{
|
|
wait_ack_index++;
|
|
}
|
|
|
|
/* check acknowledge */
|
|
if(can_x->msts_bit.fzc)
|
|
{
|
|
/* set the time triggered communication mode */
|
|
can_x->mctrl_bit.ttcen = can_base_struct->ttc_enable;
|
|
|
|
/* set the automatic exit bus-off management */
|
|
can_x->mctrl_bit.aeboen = can_base_struct->aebo_enable;
|
|
|
|
/* set the automatic automatic exit doze mode */
|
|
can_x->mctrl_bit.aeden = can_base_struct->aed_enable;
|
|
|
|
/* set the prohibit retransmission when sending fails */
|
|
can_x->mctrl_bit.prsfen = can_base_struct->prsf_enable;
|
|
|
|
/* set the message discarding rule select when overflow */
|
|
can_x->mctrl_bit.mdrsel = can_base_struct->mdrsel_selection;
|
|
|
|
/* set the multiple message sending sequence rule */
|
|
can_x->mctrl_bit.mmssr = can_base_struct->mmssr_selection;
|
|
|
|
/* set the test mode */
|
|
can_x->btmg_bit.lben = can_base_struct->mode_selection & 0x01;
|
|
can_x->btmg_bit.loen = (can_base_struct->mode_selection >> 1) & 0x01;
|
|
|
|
/* request leave freeze mode */
|
|
can_x->mctrl_bit.fzen = FALSE;
|
|
|
|
/* wait the acknowledge */
|
|
wait_ack_index = 0;
|
|
while((can_x->msts_bit.fzc) && (wait_ack_index != FZC_TIMEOUT))
|
|
{
|
|
wait_ack_index++;
|
|
}
|
|
|
|
/* check acknowledged */
|
|
if(can_x->msts_bit.fzc)
|
|
{
|
|
init_status_index = ERROR;
|
|
}
|
|
else
|
|
{
|
|
init_status_index = SUCCESS ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
init_status_index = ERROR;
|
|
}
|
|
|
|
/* return the status of initialization */
|
|
return init_status_index;
|
|
}
|
|
|
|
/**
|
|
* @brief fill each can_filter_init_struct member with its default value.
|
|
* @param can_filter_init_struct: pointer to a can_filter_init_type structure which will be initialized.
|
|
* @retval none.
|
|
*/
|
|
void can_filter_default_para_init(can_filter_init_type* can_filter_init_struct)
|
|
{
|
|
/* reset can filter init structure parameters values */
|
|
|
|
/* initialize the filter activate state */
|
|
can_filter_init_struct->filter_activate_enable = FALSE;
|
|
|
|
/* filter mode */
|
|
can_filter_init_struct->filter_mode = CAN_FILTER_MODE_ID_MASK;
|
|
|
|
/* filter relation fifo select */
|
|
can_filter_init_struct->filter_fifo = CAN_FILTER_FIFO0;
|
|
|
|
/* filter number select */
|
|
can_filter_init_struct->filter_number = 0;
|
|
|
|
/* initialize the filter bit width */
|
|
can_filter_init_struct->filter_bit = CAN_FILTER_16BIT;
|
|
|
|
/* initialize the filters filter data bit */
|
|
can_filter_init_struct->filter_id_high = 0;
|
|
can_filter_init_struct->filter_id_low = 0;
|
|
can_filter_init_struct->filter_mask_high = 0;
|
|
can_filter_init_struct->filter_mask_low = 0;
|
|
}
|
|
|
|
/**
|
|
* @brief initialize the can peripheral according to the specified
|
|
* parameters in the can_filter_init_struct.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @param can_filter_init_struct: pointer to a can_filter_init_type structure that contains the configuration information.
|
|
* @retval none.
|
|
*/
|
|
void can_filter_init(can_type* can_x, can_filter_init_type* can_filter_init_struct)
|
|
{
|
|
uint32_t filter_number_bit_pos = 0;
|
|
filter_number_bit_pos = ((uint32_t)1) << can_filter_init_struct->filter_number;
|
|
/* set the filter turn into configuration condition */
|
|
can_x->fctrl_bit.fcs = TRUE;
|
|
|
|
/* filter activate disable */
|
|
can_x->facfg &= ~(uint32_t)filter_number_bit_pos;
|
|
|
|
/* filter bit width */
|
|
switch(can_filter_init_struct->filter_bit)
|
|
{
|
|
case CAN_FILTER_16BIT:
|
|
can_x->fbwcfg &= ~(uint32_t)filter_number_bit_pos;
|
|
/* first 16-bit identifier and first 16-bit mask or first 16-bit identifier and second 16-bit identifier */
|
|
can_x->ffb[can_filter_init_struct->filter_number].ffdb1 = ((0x0000FFFF & (uint32_t)can_filter_init_struct->filter_mask_low) << 16);
|
|
can_x->ffb[can_filter_init_struct->filter_number].ffdb1 |= (0x0000FFFF & (uint32_t)can_filter_init_struct->filter_id_low);
|
|
|
|
/* second 16-bit identifier and second 16-bit mask or third 16-bit identifier and fourth 16-bit identifier */
|
|
can_x->ffb[can_filter_init_struct->filter_number].ffdb2 = ((0x0000FFFF & (uint32_t)can_filter_init_struct->filter_mask_high) << 16);
|
|
can_x->ffb[can_filter_init_struct->filter_number].ffdb2 |= (0x0000FFFF & (uint32_t)can_filter_init_struct->filter_id_high);
|
|
|
|
break;
|
|
case CAN_FILTER_32BIT:
|
|
can_x->fbwcfg |= filter_number_bit_pos;
|
|
/* 32-bit identifier or first 32-bit identifier */
|
|
can_x->ffb[can_filter_init_struct->filter_number].ffdb1 = ((0x0000FFFF & (uint32_t)can_filter_init_struct->filter_id_high) << 16);
|
|
can_x->ffb[can_filter_init_struct->filter_number].ffdb1 |= (0x0000FFFF & (uint32_t)can_filter_init_struct->filter_id_low);
|
|
|
|
/* 32-bit mask or second 32-bit identifier */
|
|
can_x->ffb[can_filter_init_struct->filter_number].ffdb2 = ((0x0000FFFF & (uint32_t)can_filter_init_struct->filter_mask_high) << 16);
|
|
can_x->ffb[can_filter_init_struct->filter_number].ffdb2 |= (0x0000FFFF & (uint32_t)can_filter_init_struct->filter_mask_low);
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* filter mode */
|
|
switch(can_filter_init_struct->filter_mode)
|
|
{
|
|
case CAN_FILTER_MODE_ID_MASK:
|
|
can_x->fmcfg &= ~(uint32_t)filter_number_bit_pos;
|
|
break;
|
|
case CAN_FILTER_MODE_ID_LIST:
|
|
can_x->fmcfg |= (uint32_t)filter_number_bit_pos;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* filter relation fifo select */
|
|
switch(can_filter_init_struct->filter_fifo)
|
|
{
|
|
case CAN_FILTER_FIFO0:
|
|
can_x->frf &= ~(uint32_t)filter_number_bit_pos;
|
|
break;
|
|
case CAN_FILTER_FIFO1:
|
|
can_x->frf |= (uint32_t)filter_number_bit_pos;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* filter activate enable */
|
|
switch(can_filter_init_struct->filter_activate_enable)
|
|
{
|
|
case TRUE:
|
|
can_x->facfg |= (uint32_t)filter_number_bit_pos;
|
|
break;
|
|
case FALSE:
|
|
can_x->facfg &= ~(uint32_t)filter_number_bit_pos;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* set the filter turn into working condition */
|
|
can_x->fctrl_bit.fcs = FALSE;
|
|
}
|
|
|
|
/**
|
|
* @brief enable or disable the debug transmission prohibit of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @param new_state: new state of debug transmission prohibit.
|
|
* this parameter can be: TRUE or FALSE.
|
|
* @retval none.
|
|
*/
|
|
void can_debug_transmission_prohibit(can_type* can_x, confirm_state new_state)
|
|
{
|
|
can_x->mctrl_bit.ptd = new_state;
|
|
}
|
|
|
|
/**
|
|
* @brief enable or disable time trigger operation communication mode of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1 or CAN2.
|
|
* @param new_state : new state of time trigger operation communication mode.
|
|
* this parameter can be: TRUE or FALSE.
|
|
* @note
|
|
* note1:
|
|
* when enabled, transmit mailbox time stamp(tmts[15:0]) value is sent in the last two data bytes of
|
|
* the 8-byte message: tmts[7:0] in data byte 6 and tmts[15:8] in data byte 7
|
|
* @note
|
|
* note2:
|
|
* tmdtbl must be programmed as 8 in order time stamp (2 bytes) to be sent over the can bus.
|
|
* @retval none
|
|
*/
|
|
void can_ttc_mode_enable(can_type* can_x, confirm_state new_state)
|
|
{
|
|
/* config the ttc mode new_state */
|
|
can_x->mctrl_bit.ttcen = new_state;
|
|
|
|
/* config tmtsten bits new_state */
|
|
can_x->tx_mailbox[0].tmc_bit.tmtsten = new_state;
|
|
can_x->tx_mailbox[1].tmc_bit.tmtsten = new_state;
|
|
can_x->tx_mailbox[2].tmc_bit.tmtsten = new_state;
|
|
}
|
|
|
|
/**
|
|
* @brief fill the transmission message and transmit of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @param tx_message_struct: pointer to a structure which contains the message to be trans.
|
|
* @retval the number of the mailbox that is used for transmission:
|
|
* this parameter can be one of the following values:
|
|
* - CAN_TX_MAILBOX0
|
|
* - CAN_TX_MAILBOX1
|
|
* - CAN_TX_MAILBOX2
|
|
* - CAN_TX_STATUS_NO_EMPTY <meanings there is no empty mailbox, message cannot be filled>
|
|
*/
|
|
uint8_t can_message_transmit(can_type* can_x, can_tx_message_type* tx_message_struct)
|
|
{
|
|
uint8_t transmit_mailbox = CAN_TX_STATUS_NO_EMPTY;
|
|
|
|
/* select one empty transmit mailbox */
|
|
if(can_x->tsts_bit.tm0ef)
|
|
{
|
|
transmit_mailbox = CAN_TX_MAILBOX0;
|
|
}
|
|
else if(can_x->tsts_bit.tm1ef)
|
|
{
|
|
transmit_mailbox = CAN_TX_MAILBOX1;
|
|
}
|
|
else if(can_x->tsts_bit.tm2ef)
|
|
{
|
|
transmit_mailbox = CAN_TX_MAILBOX2;
|
|
}
|
|
else
|
|
{
|
|
transmit_mailbox = CAN_TX_STATUS_NO_EMPTY;
|
|
}
|
|
|
|
if(transmit_mailbox != CAN_TX_STATUS_NO_EMPTY)
|
|
{
|
|
/* set up the id */
|
|
can_x->tx_mailbox[transmit_mailbox].tmi &= 0x00000001;
|
|
can_x->tx_mailbox[transmit_mailbox].tmi_bit.tmidsel = tx_message_struct->id_type;
|
|
switch(tx_message_struct->id_type)
|
|
{
|
|
case CAN_ID_STANDARD:
|
|
can_x->tx_mailbox[transmit_mailbox].tmi_bit.tmsid = tx_message_struct->standard_id;
|
|
break;
|
|
case CAN_ID_EXTENDED:
|
|
can_x->tx_mailbox[transmit_mailbox].tmi |= (tx_message_struct->extended_id << 3);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
can_x->tx_mailbox[transmit_mailbox].tmi_bit.tmfrsel = tx_message_struct->frame_type;
|
|
/* set up the dlc */
|
|
can_x->tx_mailbox[transmit_mailbox].tmc_bit.tmdtbl = (tx_message_struct->dlc & ((uint8_t)0x0F));
|
|
|
|
/* set up the data field */
|
|
can_x->tx_mailbox[transmit_mailbox].tmdtl = (((uint32_t)tx_message_struct->data[3] << 24) |
|
|
((uint32_t)tx_message_struct->data[2] << 16) |
|
|
((uint32_t)tx_message_struct->data[1] << 8) |
|
|
((uint32_t)tx_message_struct->data[0]));
|
|
can_x->tx_mailbox[transmit_mailbox].tmdth = (((uint32_t)tx_message_struct->data[7] << 24) |
|
|
((uint32_t)tx_message_struct->data[6] << 16) |
|
|
((uint32_t)tx_message_struct->data[5] << 8) |
|
|
((uint32_t)tx_message_struct->data[4]));
|
|
|
|
/* request transmission */
|
|
can_x->tx_mailbox[transmit_mailbox].tmi_bit.tmsr = TRUE;
|
|
}
|
|
return transmit_mailbox;
|
|
}
|
|
|
|
/**
|
|
* @brief check the transmission state of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1 or CAN2.
|
|
* @param transmit_mailbox: the number of the mailbox that is used for transmission.
|
|
* this parameter can be one of the following values:
|
|
* - CAN_TX_MAILBOX0
|
|
* - CAN_TX_MAILBOX1
|
|
* - CAN_TX_MAILBOX2
|
|
* @retval can transmit status
|
|
* this parameter can be one of the following values:
|
|
* - CAN_TX_STATUS_SUCCESSFUL
|
|
* - CAN_TX_STATUS_FAILED
|
|
* - CAN_TX_STATUS_PENDING
|
|
*/
|
|
can_transmit_status_type can_transmit_status_get(can_type* can_x, can_tx_mailbox_num_type transmit_mailbox)
|
|
{
|
|
can_transmit_status_type state_index = CAN_TX_STATUS_FAILED;
|
|
switch(transmit_mailbox)
|
|
{
|
|
case CAN_TX_MAILBOX0:
|
|
if(can_x->tsts_bit.tm0tcf != RESET)
|
|
{
|
|
if(can_x->tsts_bit.tm0tsf != RESET)
|
|
{
|
|
state_index = CAN_TX_STATUS_SUCCESSFUL;
|
|
}
|
|
else
|
|
{
|
|
state_index = CAN_TX_STATUS_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
state_index = CAN_TX_STATUS_PENDING;
|
|
}
|
|
break;
|
|
case CAN_TX_MAILBOX1:
|
|
if(can_x->tsts_bit.tm1tcf != RESET)
|
|
{
|
|
if(can_x->tsts_bit.tm1tsf != RESET)
|
|
{
|
|
state_index = CAN_TX_STATUS_SUCCESSFUL;
|
|
}
|
|
else
|
|
{
|
|
state_index = CAN_TX_STATUS_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
state_index = CAN_TX_STATUS_PENDING;
|
|
}
|
|
break;
|
|
case CAN_TX_MAILBOX2:
|
|
if(can_x->tsts_bit.tm2tcf != RESET)
|
|
{
|
|
if(can_x->tsts_bit.tm2tsf != RESET)
|
|
{
|
|
state_index = CAN_TX_STATUS_SUCCESSFUL;
|
|
}
|
|
else
|
|
{
|
|
state_index = CAN_TX_STATUS_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
state_index = CAN_TX_STATUS_PENDING;
|
|
}
|
|
break;
|
|
default:
|
|
state_index = CAN_TX_STATUS_FAILED;
|
|
break;
|
|
}
|
|
return state_index;
|
|
}
|
|
|
|
/**
|
|
* @brief cancel a transmit request of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1 or CAN2.
|
|
* @param mailbox: mailbox number.
|
|
* this parameter can be one of the following values:
|
|
* - CAN_TX_MAILBOX0
|
|
* - CAN_TX_MAILBOX1
|
|
* - CAN_TX_MAILBOX2
|
|
* @retval none.
|
|
*/
|
|
void can_transmit_cancel(can_type* can_x, can_tx_mailbox_num_type transmit_mailbox)
|
|
{
|
|
switch (transmit_mailbox)
|
|
{
|
|
case CAN_TX_MAILBOX0:
|
|
can_x->tsts = CAN_TSTS_TM0CT_VAL;
|
|
break;
|
|
case CAN_TX_MAILBOX1:
|
|
can_x->tsts = CAN_TSTS_TM1CT_VAL;
|
|
break;
|
|
case CAN_TX_MAILBOX2:
|
|
can_x->tsts = CAN_TSTS_TM2CT_VAL;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief receive message of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @param fifo_number: receive fifo number.
|
|
* this parameter can be one of the following values:
|
|
* - CAN_RX_FIFO0
|
|
* - CAN_RX_FIFO1
|
|
* @param rx_message_struct: pointer to a structure which store the receive message.
|
|
* @retval none.
|
|
*/
|
|
void can_message_receive(can_type* can_x, can_rx_fifo_num_type fifo_number, can_rx_message_type* rx_message_struct)
|
|
{
|
|
/* get the id type */
|
|
rx_message_struct->id_type = (can_identifier_type)can_x->fifo_mailbox[fifo_number].rfi_bit.rfidi;
|
|
switch (rx_message_struct->id_type)
|
|
{
|
|
case CAN_ID_STANDARD:
|
|
rx_message_struct->standard_id = can_x->fifo_mailbox[fifo_number].rfi_bit.rfsid;
|
|
break;
|
|
case CAN_ID_EXTENDED:
|
|
rx_message_struct->extended_id = 0x1FFFFFFF & (can_x->fifo_mailbox[fifo_number].rfi >> 3);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
rx_message_struct->frame_type = (can_trans_frame_type)can_x->fifo_mailbox[fifo_number].rfi_bit.rffri;
|
|
/* get the dlc */
|
|
rx_message_struct->dlc = can_x->fifo_mailbox[fifo_number].rfc_bit.rfdtl;
|
|
|
|
/* get the filter match number */
|
|
rx_message_struct->filter_index = can_x->fifo_mailbox[fifo_number].rfc_bit.rffmn;
|
|
|
|
/* get the data field */
|
|
rx_message_struct->data[0] = can_x->fifo_mailbox[fifo_number].rfdtl_bit.rfdt0;
|
|
rx_message_struct->data[1] = can_x->fifo_mailbox[fifo_number].rfdtl_bit.rfdt1;
|
|
rx_message_struct->data[2] = can_x->fifo_mailbox[fifo_number].rfdtl_bit.rfdt2;
|
|
rx_message_struct->data[3] = can_x->fifo_mailbox[fifo_number].rfdtl_bit.rfdt3;
|
|
rx_message_struct->data[4] = can_x->fifo_mailbox[fifo_number].rfdth_bit.rfdt4;
|
|
rx_message_struct->data[5] = can_x->fifo_mailbox[fifo_number].rfdth_bit.rfdt5;
|
|
rx_message_struct->data[6] = can_x->fifo_mailbox[fifo_number].rfdth_bit.rfdt6;
|
|
rx_message_struct->data[7] = can_x->fifo_mailbox[fifo_number].rfdth_bit.rfdt7;
|
|
|
|
/* release the fifo */
|
|
can_receive_fifo_release(can_x, fifo_number);
|
|
}
|
|
|
|
/**
|
|
* @brief release the specified fifo of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @param fifo_number: fifo to be release.
|
|
* this parameter can be one of the following values:
|
|
* - CAN_RX_FIFO0
|
|
* - CAN_RX_FIFO1
|
|
* @retval none.
|
|
*/
|
|
void can_receive_fifo_release(can_type* can_x, can_rx_fifo_num_type fifo_number)
|
|
{
|
|
switch (fifo_number)
|
|
{
|
|
case CAN_RX_FIFO0:
|
|
can_x->rf0 = CAN_RF0_RF0R_VAL;
|
|
break;
|
|
case CAN_RX_FIFO1:
|
|
can_x->rf1 = CAN_RF1_RF1R_VAL;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief return the number of pending messages of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @param fifo_number: receive fifo number.
|
|
* this parameter can be one of the following values:
|
|
* - CAN_RX_FIFO0
|
|
* - CAN_RX_FIFO1
|
|
* @retval the number of message pending in the receive fifo.
|
|
*/
|
|
uint8_t can_receive_message_pending_get(can_type* can_x, can_rx_fifo_num_type fifo_number)
|
|
{
|
|
uint8_t message_pending = 0;
|
|
switch (fifo_number)
|
|
{
|
|
case CAN_RX_FIFO0:
|
|
message_pending = can_x->rf0_bit.rf0mn;
|
|
break;
|
|
case CAN_RX_FIFO1:
|
|
message_pending = can_x->rf1_bit.rf1mn;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return message_pending;
|
|
}
|
|
|
|
/**
|
|
* @brief set the operation mode of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @param can_operating_mode: can operating mode.
|
|
* this parameter can be one of the following values:
|
|
* - CAN_OPERATINGMODE_FREEZE
|
|
* - CAN_OPERATINGMODE_DOZE
|
|
* - CAN_OPERATINGMODE_COMMUNICATE
|
|
* @retval status of operation mode set
|
|
* this parameter can be one of the following values:
|
|
* SUCCESS or ERROR
|
|
*/
|
|
error_status can_operating_mode_set(can_type* can_x, can_operating_mode_type can_operating_mode)
|
|
{
|
|
error_status status = ERROR;
|
|
uint32_t time_out_index = FZC_TIMEOUT;
|
|
|
|
if (can_operating_mode == CAN_OPERATINGMODE_FREEZE)
|
|
{
|
|
/* request enter freeze mode */
|
|
can_x->mctrl_bit.dzen = FALSE;
|
|
can_x->mctrl_bit.fzen = TRUE;
|
|
|
|
while(((can_x->msts_bit.dzc) || (!can_x->msts_bit.fzc)) && (time_out_index != 0))
|
|
{
|
|
time_out_index--;
|
|
}
|
|
if((can_x->msts_bit.dzc) || (!can_x->msts_bit.fzc))
|
|
{
|
|
status = ERROR;
|
|
}
|
|
else
|
|
{
|
|
status = SUCCESS;
|
|
}
|
|
}
|
|
else if(can_operating_mode == CAN_OPERATINGMODE_DOZE)
|
|
{
|
|
/* request enter doze mode */
|
|
can_x->mctrl_bit.dzen = TRUE;
|
|
can_x->mctrl_bit.fzen = FALSE;
|
|
|
|
while(((!can_x->msts_bit.dzc) || (can_x->msts_bit.fzc)) && (time_out_index != 0))
|
|
{
|
|
time_out_index--;
|
|
}
|
|
if((!can_x->msts_bit.dzc) || (can_x->msts_bit.fzc))
|
|
{
|
|
status = ERROR;
|
|
}
|
|
else
|
|
{
|
|
status = SUCCESS;
|
|
}
|
|
}
|
|
else if(can_operating_mode == CAN_OPERATINGMODE_COMMUNICATE)
|
|
{
|
|
/* request enter normal mode */
|
|
can_x->mctrl_bit.dzen = FALSE;
|
|
can_x->mctrl_bit.fzen = FALSE;
|
|
|
|
while(((can_x->msts_bit.dzc) || (can_x->msts_bit.fzc)) && (time_out_index != 0))
|
|
{
|
|
time_out_index--;
|
|
}
|
|
if((can_x->msts_bit.dzc) || (can_x->msts_bit.fzc))
|
|
{
|
|
status = ERROR;
|
|
}
|
|
else
|
|
{
|
|
status = SUCCESS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
status = ERROR;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* @brief enter the low power mode of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @retval status of doze mode enter, the returned value can be:
|
|
* - CAN_ENTER_DOZE_SUCCESSFUL <it meaning enter the doze mode succeed>
|
|
* - CAN_ENTER_DOZE_FAILED <it meaning enter the doze mode failed>
|
|
*/
|
|
can_enter_doze_status_type can_doze_mode_enter(can_type* can_x)
|
|
{
|
|
can_enter_doze_status_type status = CAN_ENTER_DOZE_FAILED;
|
|
uint32_t time_out_index = FZC_TIMEOUT;
|
|
can_x->mctrl_bit.fzen = FALSE;
|
|
can_x->mctrl_bit.dzen = TRUE;
|
|
while(((!can_x->msts_bit.dzc) || (can_x->msts_bit.fzc)) && (time_out_index != 0))
|
|
{
|
|
time_out_index--;
|
|
}
|
|
if((!can_x->msts_bit.dzc) || (can_x->msts_bit.fzc))
|
|
{
|
|
status = CAN_ENTER_DOZE_FAILED;
|
|
}
|
|
else
|
|
{
|
|
status = CAN_ENTER_DOZE_SUCCESSFUL;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* @brief exit the doze mode of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @retval status of doze mode enter, the returned value can be:
|
|
* - CAN_QUIT_DOZE_SUCCESSFUL <it meaning exit the doze mode succeed>
|
|
* - CAN_QUIT_DOZE_FAILED <it meaning exit the doze mode failed>
|
|
*/
|
|
can_quit_doze_status_type can_doze_mode_exit(can_type* can_x)
|
|
{
|
|
can_quit_doze_status_type status = CAN_QUIT_DOZE_FAILED;
|
|
uint32_t time_out_index = DZC_TIMEOUT;
|
|
can_x->mctrl_bit.dzen = FALSE;
|
|
while((can_x->msts_bit.dzc) && (time_out_index != 0))
|
|
{
|
|
time_out_index--;
|
|
}
|
|
if(!can_x->msts_bit.dzc)
|
|
{
|
|
status = CAN_QUIT_DOZE_SUCCESSFUL;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* @brief return the error type record (etr) of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @retval the value of the error code
|
|
* the return can be one of the follow values:
|
|
* - CAN_ERRORRECORD_NOERR
|
|
* - CAN_ERRORRECORD_STUFFERR,
|
|
* - CAN_ERRORRECORD_FORMERR,
|
|
* - CAN_ERRORRECORD_ACKERR,
|
|
* - CAN_ERRORRECORD_BITRECESSIVEERR,
|
|
* - CAN_ERRORRECORD_BITDOMINANTERR,
|
|
* - CAN_ERRORRECORD_CRCERR,
|
|
* - CAN_ERRORRECORD_SOFTWARESETERR
|
|
*/
|
|
can_error_record_type can_error_type_record_get(can_type* can_x)
|
|
{
|
|
can_error_record_type error_code = CAN_ERRORRECORD_NOERR;
|
|
|
|
error_code = (can_error_record_type)can_x->ests_bit.etr;
|
|
return error_code;
|
|
}
|
|
|
|
/**
|
|
* @brief return the receive error counter (rec) of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @retval the value of receive error counter.
|
|
*/
|
|
uint8_t can_receive_error_counter_get(can_type* can_x)
|
|
{
|
|
uint8_t counter = 0;
|
|
counter = can_x->ests_bit.rec;
|
|
return counter;
|
|
}
|
|
|
|
/**
|
|
* @brief return the transmit error counter of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @retval the value of transmit error counter.
|
|
*/
|
|
uint8_t can_transmit_error_counter_get(can_type* can_x)
|
|
{
|
|
uint8_t counter = 0;
|
|
counter = can_x->ests_bit.tec;
|
|
return counter;
|
|
}
|
|
|
|
/**
|
|
* @brief enable or disable the interrupt of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @param can_int: specifies the can interrupt sources to be enabled or disabled.
|
|
* this parameter can be one of the following values:
|
|
* - CAN_TCIEN_INT
|
|
* - CAN_RF0MIEN_INT
|
|
* - CAN_RF0FIEN_INT
|
|
* - CAN_RF0OIEN_INT
|
|
* - CAN_RF1MIEN_INT
|
|
* - CAN_RF1FIEN_INT
|
|
* - CAN_RF1OIEN_INT
|
|
* - CAN_EAIEN_INT
|
|
* - CAN_EPIEN_INT
|
|
* - CAN_BOIEN_INT
|
|
* - CAN_ETRIEN_INT
|
|
* - CAN_EOIEN_INT
|
|
* - CAN_QDZIEN_INT
|
|
* - CAN_EDZIEN_INT
|
|
* @param new_state: new state of the can interrupts.
|
|
* this parameter can be: TRUE or FALSE.
|
|
* @retval none.
|
|
*/
|
|
void can_interrupt_enable(can_type* can_x, uint32_t can_int, confirm_state new_state)
|
|
{
|
|
if (new_state != FALSE)
|
|
{
|
|
can_x->inten |= can_int;
|
|
}
|
|
else
|
|
{
|
|
can_x->inten &= ~can_int;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief get flag of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @param can_flag: select the flag.
|
|
* this parameter can be one of the following flags:
|
|
* - CAN_EAF_FLAG
|
|
* - CAN_EPF_FLAG
|
|
* - CAN_BOF_FLAG
|
|
* - CAN_ETR_FLAG
|
|
* - CAN_EOIF_FLAG
|
|
* - CAN_TM0TCF_FLAG
|
|
* - CAN_TM1TCF_FLAG
|
|
* - CAN_TM2TCF_FLAG
|
|
* - CAN_RF0MN_FLAG
|
|
* - CAN_RF0FF_FLAG
|
|
* - CAN_RF0OF_FLAG
|
|
* - CAN_RF1MN_FLAG
|
|
* - CAN_RF1FF_FLAG
|
|
* - CAN_RF1OF_FLAG
|
|
* - CAN_QDZIF_FLAG
|
|
* - CAN_EDZC_FLAG
|
|
* - CAN_TMEF_FLAG
|
|
* note:the state of CAN_EDZC_FLAG need to check dzc and edzif bit
|
|
* note:the state of CAN_TMEF_FLAG need to check rqc0,rqc1 and rqc2 bit
|
|
* @retval status of can_flag, the returned value can be:SET or RESET.
|
|
*/
|
|
flag_status can_flag_get(can_type* can_x, uint32_t can_flag)
|
|
{
|
|
flag_status bit_status = RESET;
|
|
switch(can_flag)
|
|
{
|
|
case CAN_EAF_FLAG:
|
|
bit_status = (flag_status)can_x->ests_bit.eaf;
|
|
break;
|
|
case CAN_EPF_FLAG:
|
|
bit_status = (flag_status)can_x->ests_bit.epf;
|
|
break;
|
|
case CAN_BOF_FLAG:
|
|
bit_status = (flag_status)can_x->ests_bit.bof;
|
|
break;
|
|
case CAN_ETR_FLAG:
|
|
if(can_x->ests_bit.etr != 0)
|
|
{
|
|
bit_status = SET;
|
|
}
|
|
else
|
|
{
|
|
bit_status = RESET;
|
|
}
|
|
break;
|
|
case CAN_EOIF_FLAG:
|
|
bit_status = (flag_status)can_x->msts_bit.eoif;
|
|
break;
|
|
case CAN_TM0TCF_FLAG:
|
|
bit_status = (flag_status)can_x->tsts_bit.tm0tcf;
|
|
break;
|
|
case CAN_TM1TCF_FLAG:
|
|
bit_status = (flag_status)can_x->tsts_bit.tm1tcf;
|
|
break;
|
|
case CAN_TM2TCF_FLAG:
|
|
bit_status = (flag_status)can_x->tsts_bit.tm2tcf;
|
|
break;
|
|
case CAN_RF0MN_FLAG:
|
|
if(can_x->rf0_bit.rf0mn != 0)
|
|
{
|
|
bit_status = SET;
|
|
}
|
|
else
|
|
{
|
|
bit_status = RESET;
|
|
}
|
|
break;
|
|
case CAN_RF0FF_FLAG:
|
|
bit_status = (flag_status)can_x->rf0_bit.rf0ff;
|
|
break;
|
|
case CAN_RF0OF_FLAG:
|
|
bit_status = (flag_status)can_x->rf0_bit.rf0of;
|
|
break;
|
|
case CAN_RF1MN_FLAG:
|
|
if(can_x->rf1_bit.rf1mn != 0)
|
|
{
|
|
bit_status = SET;
|
|
}
|
|
else
|
|
{
|
|
bit_status = RESET;
|
|
}
|
|
break;
|
|
case CAN_RF1FF_FLAG:
|
|
bit_status = (flag_status)can_x->rf1_bit.rf1ff;
|
|
break;
|
|
case CAN_RF1OF_FLAG:
|
|
bit_status = (flag_status)can_x->rf1_bit.rf1of;
|
|
break;
|
|
case CAN_QDZIF_FLAG:
|
|
bit_status = (flag_status)can_x->msts_bit.qdzif;
|
|
break;
|
|
case CAN_EDZC_FLAG:
|
|
if((can_x->msts_bit.dzc != RESET) ||(can_x->msts_bit.edzif != RESET))
|
|
{
|
|
bit_status = SET;
|
|
}
|
|
else
|
|
{
|
|
bit_status = RESET;
|
|
}
|
|
break;
|
|
case CAN_TMEF_FLAG:
|
|
if((can_x->tsts_bit.tm0ef != RESET) || (can_x->tsts_bit.tm1ef != RESET) || (can_x->tsts_bit.tm2ef != RESET))
|
|
{
|
|
bit_status = SET;
|
|
}
|
|
else
|
|
{
|
|
bit_status = RESET;
|
|
}
|
|
break;
|
|
default:
|
|
bit_status = RESET;
|
|
break;
|
|
}
|
|
return bit_status;
|
|
}
|
|
|
|
/**
|
|
* @brief clear flag of the specified can peripheral.
|
|
* @param can_x: select the can peripheral.
|
|
* this parameter can be one of the following values:
|
|
* CAN1,CAN2.
|
|
* @param can_flag: select the flag.
|
|
* this parameter can be one of the following flags:
|
|
* - CAN_EAF_FLAG
|
|
* - CAN_EPF_FLAG
|
|
* - CAN_BOF_FLAG
|
|
* - CAN_ETR_FLAG
|
|
* - CAN_EOIF_FLAG
|
|
* - CAN_TM0TCF_FLAG
|
|
* - CAN_TM1TCF_FLAG
|
|
* - CAN_TM2TCF_FLAG
|
|
* - CAN_RF0FF_FLAG
|
|
* - CAN_RF0OF_FLAG
|
|
* - CAN_RF1FF_FLAG
|
|
* - CAN_RF1OF_FLAG
|
|
* - CAN_QDZIF_FLAG
|
|
* - CAN_EDZC_FLAG
|
|
* - CAN_TMEF_FLAG
|
|
* note:CAN_RF0MN_FLAG and CAN_RF1MN_FLAG can not clear by this function
|
|
* @retval none.
|
|
*/
|
|
void can_flag_clear(can_type* can_x, uint32_t can_flag)
|
|
{
|
|
switch(can_flag)
|
|
{
|
|
case CAN_EAF_FLAG:
|
|
case CAN_EPF_FLAG:
|
|
case CAN_BOF_FLAG:
|
|
case CAN_EOIF_FLAG:
|
|
can_x->msts = CAN_MSTS_EOIF_VAL;
|
|
break;
|
|
case CAN_ETR_FLAG:
|
|
can_x->msts = CAN_MSTS_EOIF_VAL;
|
|
can_x->ests = 0;
|
|
break;
|
|
case CAN_TM0TCF_FLAG:
|
|
can_x->tsts = CAN_TSTS_TM0TCF_VAL;
|
|
break;
|
|
case CAN_TM1TCF_FLAG:
|
|
can_x->tsts = CAN_TSTS_TM1TCF_VAL;
|
|
break;
|
|
case CAN_TM2TCF_FLAG:
|
|
can_x->tsts = CAN_TSTS_TM2TCF_VAL;
|
|
break;
|
|
case CAN_RF0FF_FLAG:
|
|
can_x->rf0 = CAN_RF0_RF0FF_VAL;
|
|
break;
|
|
case CAN_RF0OF_FLAG:
|
|
can_x->rf0 = CAN_RF0_RF0OF_VAL;
|
|
break;
|
|
case CAN_RF1FF_FLAG:
|
|
can_x->rf1 = CAN_RF1_RF1FF_VAL;
|
|
break;
|
|
case CAN_RF1OF_FLAG:
|
|
can_x->rf1 = CAN_RF1_RF1OF_VAL;
|
|
break;
|
|
case CAN_QDZIF_FLAG:
|
|
can_x->msts = CAN_MSTS_QDZIF_VAL;
|
|
break;
|
|
case CAN_EDZC_FLAG:
|
|
can_x->msts = CAN_MSTS_EDZIF_VAL;
|
|
break;
|
|
case CAN_TMEF_FLAG:
|
|
can_x->tsts = CAN_TSTS_TM0TCF_VAL | CAN_TSTS_TM1TCF_VAL | CAN_TSTS_TM2TCF_VAL;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
#endif
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/**
|
|
* @}
|
|
*/
|