AT32F435_437_Firmware_Library/libraries/drivers/src/at32f435_437_can.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
/**
* @}
*/
/**
* @}
*/