2024-07-04 20:15:18 +08:00

985 lines
32 KiB
C

/*********************************************************************************************************************
* Copyright (c) 2021, Infineon Technologies AG
*
*
* Distributed under the Boost Software License, Version 1.0.
*
*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*********************************************************************************************************************/
/********************************************************************************************************
* @file TLE926x.c
*
* @brief Implementation of main library functions
*
* @version V1.0.0
* @date
* @author Fedy Farhat
* @author Michael Schaffarczyk
********************************************************************************************************/
/* ================================================================================ */
/* ============================ HEADER FILES ================================ */
/* ================================================================================ */
#include "TLE926x.h"
#include "SBC_TLE926x.h"
#include <stdio.h>
#include "plib_port.h"
/* ================================================================================ */
/* ============================== Variables ================================= */
/* ================================================================================ */
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
static uint8_t wd_config;
/* -------------------------------- ISR Handling --------------------------------- */
static SBC_Func_Callback SBC_ISR_Callbacks[60];
static uint32_t SBC_ISR_Vectors[60];
static uint8_t SBC_ISR_ReadOutRegs[60];
static uint8_t SBC_ISR_ReadOutVals[60];
static uint8_t SBC_RegisteredCallbacks = 0;
static uint8_t SBC_RegisteredRedoutRegs = 0;
uint16_t SBC_Mode=0;
uint16_t SBC_Mode_VCC1=0;
uint16_t SBC_Mode_VCC2=0;
/* ================================================================================ */
/* =========================== Library Functions ============================ */
/* ================================================================================ */
/* -------------------------------- Main Functions ------------------------------- */
// trigger the Watchdog
SBC_ErrorCode sbc_wd_trigger(void) {
SBC_ErrorCode errCode;
// if (wd_config == (sbc_read_reg(SBC_WD_CTRL)&0xFF)) {
// return sbc_write_reg(SBC_WD_CTRL, wd_config, NULL);
// }
sbc_write_reg(SBC_WD_CTRL, wd_config, NULL);
// SBC_Mode_VCC2 = sbc_read_reg(SBC_SUP_STAT_1);
// SBC_Mode_VCC1 = sbc_read_reg(SBC_SUP_STAT_2);
// sbc_write_reg(SBC_M_S_CTRL,0x8,0);
// errCode.SBC_Register = SBC_WD_CTRL;
// errCode.flippedBitsMask = ((uint8_t)sbc_read_reg(SBC_WD_CTRL)) ^ wd_config;
// errCode.expectedValue = wd_config;
errCode.SBC_Register = 0;
errCode.flippedBitsMask = 0;
errCode.expectedValue = 0;
return errCode;
}
void sbc_trig_reset(void)
{
/*soft reset*/
//sbc_write_reg_field (SBC_M_S_CTRL, MODE_MASK, SBC_RESET, 0x00); // M_S_CTRL(0x81)
sbc_init();
}
// Read the addressed register
uint16_t sbc_read_reg(sbc_register_t sbc_register) {
/* Read and return data - Bit[15:8] = Status Information Field - Bit [7:0] Register data */
return SBC_SPI_TRANSFER16(SBC_READ_MASK & sbc_register, 0x00);
}
// Read register bit
uint8_t sbc_read_reg_field(sbc_register_t sbc_register, sbc_bit_mask_t bit_mask) {
uint8_t data = ((uint8_t)sbc_read_reg(sbc_register)) & 0xFFU;
return (data & bit_mask) >> SBC_BITPOSITION(bit_mask);
}
// Write value to a register
SBC_ErrorCode sbc_write_reg(sbc_register_t sbc_register, uint8_t SBC_Val, uint16_t * returnval) {
SBC_ErrorCode errCode;
uint16_t returndata = SBC_SPI_TRANSFER16(SBC_WRITE_BIT | sbc_register, SBC_Val);
if(returnval != NULL) {
*returnval = returndata;
}
// errCode.SBC_Register = sbc_register;
// errCode.flippedBitsMask = ((uint8_t)sbc_read_reg(sbc_register)) ^ SBC_Val;
// errCode.expectedValue = SBC_Val;
errCode.SBC_Register = 0;
errCode.flippedBitsMask = 0;
errCode.expectedValue = 0;
return errCode;
}
/*Write bit value in register*/
SBC_ErrorCode sbc_write_reg_field(sbc_register_t sbc_register, sbc_bit_mask_t bit_mask, uint8_t val, uint16_t * returnval) {
SBC_ErrorCode errCode;
/* Read data out of register to be manipulated */
uint16_t returndata = sbc_read_reg(sbc_register);
if(returnval != NULL) {
*returnval = returndata;
}
/* pick the first 8 bit of read SBC_Reg, meant register data [7:0]*/
uint8_t data = (uint8_t)returndata;
/* Set the used bit field to all 0 */
data &= ~(bit_mask);
/* Configure new data to bit field */
data |= (val << SBC_BITPOSITION(bit_mask));
(void)SBC_SPI_TRANSFER16(SBC_WRITE_BIT | sbc_register, data);
errCode.SBC_Register = sbc_register;
errCode.expectedValue = (val << SBC_BITPOSITION(bit_mask));
uint8_t actualValue = ((uint8_t)sbc_read_reg(sbc_register)) & bit_mask;
errCode.flippedBitsMask = errCode.expectedValue ^ actualValue;
return errCode;
}
void delay(uint32_t val)
{
volatile uint32_t temp = 0xFF;
while(val--)
{
while(temp--);
temp = 0xFF;
}
}
void CyclicTskSchM_TimerSync (void);
/* initialize SBC */
SBC_ErrorCode sbc_init(void) {
SBC_ErrorCode errCode;
uint8_t i;
uint8_t delay_cnt;
uint8_t WD_CTRL = CW_WD_CTRL;
uint8_t checksum = WD_CTRL;
uint16_t readback;
checksum = checksum ^ checksum >> 4;
checksum = checksum ^ checksum >> 2;
checksum = checksum ^ checksum >> 1;
if((checksum & 1) > 0) {
/* Set parity bit */
WD_CTRL = WD_CTRL | 0x80U; //
}
wd_config = WD_CTRL;
/* Describes initialization sequence.
init Sequence containing {reg_address, reg_value}*/
uint8_t initSequence[4][2] = {
{SBC_WD_CTRL, WD_CTRL},//0x04 TimeOut; 200ms period
{SBC_M_S_CTRL, CW_M_S_CTRL},//0x18 SBC normal;vcc3off;vcc2 on in normal;
{SBC_BUS_CTRL_1, CW_BUS_CTRL_1},//0x03 lin off; can normal
/* End Configuration */
{0x00U, 0x00U}
};
delay_cnt = 10;
do{
CyclicTskSchM_TimerSync();
}while(delay_cnt--);
/* Write all initialization items to Lite SBC
write the above defined reg_values inside the real registers on Lite SBC*/
i =0;
while(initSequence[i][0] != 0x00U || initSequence[i][1] != 0x00U) {
while((readback&0xff) != initSequence[i][1])
{
errCode = sbc_write_reg((sbc_register_t) initSequence[i][0],(sbc_register_t) initSequence[i][1], &readback);
delay(1);//test:16us
}
i++;
}
errCode.SBC_Register = 0x00;
errCode.flippedBitsMask = 0x00;
errCode.expectedValue = 0x00;
return errCode;
}
#if 0
/* initialize SBC */
SBC_ErrorCode sbc_init(void) {
SBC_ErrorCode errCode;
uint16_t famprod;
uint8_t sbc_family;
//uint8_t sbc_product;
uint8_t i;
uint8_t cond;
uint8_t delay_cnt;
uint8_t sbc_reset_init;
uint8_t sbc_init;
uint8_t sbc_init_cnt;
uint8_t WD_CTRL = CW_WD_CTRL;
//uint8_t SWK_ID3_CTRL, SWK_ID2_CTRL, SWK_ID1_CTRL, SWK_ID0_CTRL;
//uint8_t SWK_MASK_ID3_CTRL, SWK_MASK_ID2_CTRL, SWK_MASK_ID1_CTRL, SWK_MASK_ID0_CTRL;
uint8_t SWK_CAN_FD_CTRL = CW_SWK_CAN_FD_CTRL;
uint8_t checksum = WD_CTRL;
checksum = checksum ^ checksum >> 4;
checksum = checksum ^ checksum >> 2;
checksum = checksum ^ checksum >> 1;
if((checksum & 1) > 0) {
/* Set parity bit */
WD_CTRL = WD_CTRL | 0x80U; //
}
wd_config = WD_CTRL;
/* Check if ID is configured to be extended */
if((CW_SWK_ID0_CTRL & IDE_MASK ) == SBC_IDE_EXTENDED) {
} else {
}
/* DIS_ERR_CNT is set only when FD Tolerance is set.
Set DIS_ERR_CNT value to 1 if the value of CAN_FD_EN is 1 */
if((CW_SWK_CAN_FD_CTRL & CAN_FD_EN_MASK) == SBC_CAN_FD_EN_ENABLED) {
SWK_CAN_FD_CTRL |= SBC_DIS_ERR_CNT_DISABLED << SBC_BITPOSITION(DIS_ERR_CNT_MASK);
}
/* Describes initialization sequence.
init Sequence containing {reg_address, reg_value}*/
uint8_t initSequence[45][2] = {
{SBC_WD_CTRL, WD_CTRL},
{SBC_M_S_CTRL, CW_M_S_CTRL},
{SBC_BUS_CTRL_1, CW_BUS_CTRL_1},
{SBC_WK_CTRL_1, CW_WK_CTRL_1},
{0x00U, 0x00U},
{SBC_HW_CTRL, CW_HW_CTRL},
{SBC_BUS_CTRL_2, CW_BUS_CTRL_2},
{SBC_WK_CTRL_2, CW_WK_CTRL_2},
{SBC_WK_PUPD_CTRL, CW_WK_PUPD_CTRL},
{SBC_WK_FLT_CTRL, CW_WK_FLT_CTRL},
{SBC_TIMER1_CTRL, CW_TIMER1_CTRL},
{SBC_TIMER2_CTRL, CW_TIMER2_CTRL},
{SBC_SW_SD_CTRL, CW_SW_SD_CTRL},
{SBC_HS_CTRL_1, CW_HS_CTRL1},
{SBC_HS_CTRL_2, CW_HS_CTRL2},
{SBC_PWM1_CTRL, CW_PWM1_CTRL},
{SBC_PWM2_CTRL, CW_PWM2_CTRL},
{SBC_PWM_FREQ_CTRL, CW_PWM_FREQ_CTRL}, /* The desired duty cycle should be set first before GPIO is enabled as PWM HS or PWM LS. */
{SBC_GPIO_CTRL, CW_GPIO_CTRL},
/* -------------------------- SELECTIVE WAKE REGISTERS --------------------------- */
/* Configuring CDR */ // CDR = Clock and Data Recovery
{SBC_SWK_CDR_CTRL2, CW_SWK_CDR_CTRL2},
{SBC_SWK_BTL1_CTRL, CW_SWK_BTL1_CTRL},
{SBC_SWK_BTL2_CTRL, CW_SWK_BTL2_CTRL},
{SBC_SWK_CDR_LIMIT_HIGH, CW_SWK_CDR_LIMIT_HIGH_CTRL},
{SBC_SWK_CDR_LIMIT_LOW, CW_SWK_CDR_LIMIT_LOW_CTRL},
{SBC_SWK_CDR_CTRL1, ((SBC_SEL_FILT_TC16 << SBC_BITPOSITION(SELFILT_MASK)) | (SBC_CDR_EN_ENABLED << SBC_BITPOSITION(CDR_EN_MASK)))},
/* Set ID */
{SBC_SWK_ID3_CTRL, CW_SWK_ID3_CTRL},
{SBC_SWK_ID2_CTRL, CW_SWK_ID2_CTRL},
{SBC_SWK_ID1_CTRL, CW_SWK_ID1_CTRL},
{SBC_SWK_ID0_CTRL, CW_SWK_ID0_CTRL},
/* Set Mask */
{SBC_SWK_MASK_ID3_CTRL, CW_SWK_MASK_ID3_CTRL},
{SBC_SWK_MASK_ID2_CTRL, CW_SWK_MASK_ID2_CTRL},
{SBC_SWK_MASK_ID1_CTRL, CW_SWK_MASK_ID1_CTRL},
{SBC_SWK_MASK_ID0_CTRL, CW_SWK_MASK_ID0_CTRL},
/* Set Data */
{SBC_SWK_DATA7_CTRL, (uint8_t)(CW_SWK_DATA_H_CTRL >> 24)},
{SBC_SWK_DATA6_CTRL, (uint8_t)(CW_SWK_DATA_H_CTRL >> 16)},
{SBC_SWK_DATA5_CTRL, (uint8_t)(CW_SWK_DATA_H_CTRL >> 8)},
{SBC_SWK_DATA4_CTRL, (uint8_t)(CW_SWK_DATA_H_CTRL >> 0)},
{SBC_SWK_DATA3_CTRL, (uint8_t)(CW_SWK_DATA_L_CTRL >> 24)},
{SBC_SWK_DATA2_CTRL, (uint8_t)(CW_SWK_DATA_L_CTRL >> 16)},
{SBC_SWK_DATA1_CTRL, (uint8_t)(CW_SWK_DATA_L_CTRL >> 8)},
{SBC_SWK_DATA0_CTRL, (uint8_t)(CW_SWK_DATA_L_CTRL >> 0)},
/* Set DLC */
{SBC_SWK_DLC_CTRL, CW_SWK_DLC_CTRL},
{SBC_SWK_CAN_FD_CTRL, CW_SWK_CAN_FD_CTRL},
{SBC_BUS_CTRL_1, CW_BUS_CTRL_1},
/* End Configuration */
{0x00U, 0x00U}
};
/* Call SPI Init */
if(sbc_spi_init() != 0) {
errCode.SBC_Register = 0x00;
errCode.flippedBitsMask = 0x01;
errCode.expectedValue = 0x00;
return errCode;
};
/* Check if SBC is Mid-Range SBC */
famprod = sbc_read_reg(SBC_FAM_PROD_STAT);
sbc_family = (famprod & FAM_MASK) >> 8;
cond = (sbc_family == MID_RANGE_SBC_FAMILY) || (sbc_family == MID_RANGE_PLUS_SBC_FAMILY);
if (!cond) {
}
PORT_PinWrite(PORT_PIN_PA15, 1);
while(1)
{
sbc_reset_init = TRUE;
/*soft reset*/
sbc_write_reg_field (SBC_M_S_CTRL, MODE_MASK, SBC_RESET, 0x00); // M_S_CTRL(0x81)
delay_cnt = 10;
do{
CyclicTskSchM_TimerSync();
}while(delay_cnt--);
/* reset index */
i =0;
sbc_init_cnt = 0;
/* Write all initialization items to Lite SBC
write the above defined reg_values inside the real registers on Lite SBC*/
while(1)
{
sbc_init = TRUE;
while(initSequence[i][0] != 0x00U || initSequence[i][1] != 0x00U) {
errCode = sbc_write_reg((sbc_register_t) initSequence[i][0],(sbc_register_t) initSequence[i][1], NULL);
if(errCode.flippedBitsMask > 0) {
//return errCode;
sbc_init = FALSE;
break;
}
i++;
}
if(sbc_init == TRUE)
{
break;
}
else
{
sbc_init_cnt ++;
if(sbc_init_cnt >= 10)
{
sbc_reset_init = FALSE;
break;
}
}
}
if(sbc_reset_init == TRUE)/*init ok*/
{
break;
}
}
PORT_PinWrite(PORT_PIN_PA15, 0);
errCode.SBC_Register = 0x00;
errCode.flippedBitsMask = 0x00;
errCode.expectedValue = 0x00;
return errCode;
}
#endif
/* -------------------------------- ISR Functions -------------------------------- */
/* Callback function*/
void sbc_register_callback(uint32_t vector_isr, void (*Callback_Handler)(uint8_t callbackHandler)) {
/* Save callback */
SBC_ISR_Callbacks[SBC_RegisteredCallbacks] = Callback_Handler;
/* Save callback vector */
SBC_ISR_Vectors[SBC_RegisteredCallbacks] = vector_isr;
/* Check if the register will be readout already to avoid double-readout later */
uint8_t RegFound = 0;
for (uint8_t i = 0; i < SBC_RegisteredRedoutRegs; i++) {
if (SBC_ISR_ReadOutRegs[i] == ( vector_isr >> 24)) {
RegFound = 1;
}
}
/* If readout status-reg was not found, register in the readout list */
if (RegFound == 0) {
SBC_ISR_ReadOutRegs[SBC_RegisteredRedoutRegs] = (uint8_t)( vector_isr>> 24);
SBC_RegisteredRedoutRegs++;
}
SBC_RegisteredCallbacks++;
}
SBC_ErrorCode SBC_ISR(void) {
SBC_ErrorCode errCode;
/* Readout all registered status-registers */
for (uint8_t i = 0; i < SBC_RegisteredRedoutRegs; i++) {
SBC_ISR_ReadOutVals[i] = (uint8_t) sbc_read_reg( (sbc_register_t) SBC_ISR_ReadOutRegs[i]);
}
/* Handle all interrupts */
for (uint8_t i = 0; i < SBC_RegisteredCallbacks; i++) {
/* Decode ISR Vector */
uint8_t Compare = (uint8_t)SBC_ISR_Vectors[i];
uint8_t FieldPos = (uint8_t)(SBC_ISR_Vectors[i] >> 8);
uint8_t FieldMsk = (uint8_t)(SBC_ISR_Vectors[i] >> 16);
uint8_t RegAddr = (uint8_t)(SBC_ISR_Vectors[i] >> 24);
/* Readback of associated status-bit */
uint8_t ReadBack = 0;
for (uint8_t j = 0; j < SBC_RegisteredRedoutRegs; j++) {
if (SBC_ISR_ReadOutRegs[j] == RegAddr) {
ReadBack = SBC_ISR_ReadOutVals[j];
break;
}
}
/* If compare-values matched -> proceed callback and clear field */
if (((ReadBack & FieldMsk) >> FieldPos) == Compare) {
SBC_ISR_Callbacks[i](ReadBack);
}
}
/* Clear all ISR related registers */
for (uint8_t i = 0; i < SBC_RegisteredRedoutRegs; i++) {
errCode = sbc_write_reg( (sbc_register_t) SBC_ISR_ReadOutRegs[i], 0x00U, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
}
errCode.SBC_Register = 0x00U;
errCode.flippedBitsMask = 0x00U;
errCode.expectedValue = 0x00U;
return errCode;
}
/* -------------------------------- API Calls ----------------------------------- */
/* enter Normal Mode*/
SBC_ErrorCode sbc_mode_normal(void) {
return sbc_write_reg_field(SBC_M_S_CTRL, MODE_MASK, SBC_NORMAL_MODE, NULL);
}
/* enter Stop Mode*/
SBC_ErrorCode sbc_mode_stop (void) {
return sbc_write_reg_field(SBC_M_S_CTRL, MODE_MASK, SBC_STOP_MODE, NULL);
}
/* enter Sleep Mode*/
SBC_ErrorCode sbc_mode_sleep(void) {
uint8_t registerReadOut;
SBC_ErrorCode errCode;
/* Check SBC in Normal Mode */
uint8_t readData = sbc_read_reg(SBC_M_S_CTRL);
readData >>= SBC_BITPOSITION(MODE_MASK);
if (readData != SBC_NORMAL_MODE) {
errCode = sbc_mode_normal();
return errCode;
}
/* If CAN PN is configured */
if(MATH_EN_PN != 0) {
/* Reading value of SWK_STAT. */
registerReadOut = (uint8_t)sbc_read_reg(SBC_SWK_STAT);
/* The selective wake routine should be aborted if sync is not set.
Note: for SYNC to be set the transceiver must have been in Normal Mode and */
if((registerReadOut & SYNC_MASK ) >> SBC_BITPOSITION(SYNC_MASK) != SYNC_VALID_FRAME_RECEIVED) {
errCode.SBC_Register = SBC_SWK_STAT;
errCode.flippedBitsMask = SYNC_MASK;
errCode.expectedValue = SYNC_VALID_FRAME_RECEIVED << SBC_BITPOSITION(SYNC_MASK);
return errCode;
}
/* Set SWK Configuration valid */
// set CFG_VAL = 1
errCode = sbc_write_reg_field(SBC_SWK_CTRL, CFG_VAL_MASK, SBC_CFG_VAL_VALID, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
/* Clear SYSERR bit */
errCode = sbc_write_reg_field(SBC_BUS_STAT_1, SYSERR_MASK, 0x00, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
/* Set CAN Mode to off and once again to desired configuration */
// CAN OFF
errCode = sbc_write_reg_field(SBC_BUS_CTRL_1, CAN_MASK, CAN_OFF, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
// CAN ON (with SWK)
errCode = sbc_write_reg_field(SBC_BUS_CTRL_1, CAN_MASK, CAN_WAKECAPABLE_SWK, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
/* Check SWK_STAT for SYNC == 1 && SWK_SET == 1 && WUF == 0 && WUP == 0. Ignore CANSIL */
registerReadOut = (uint8_t)sbc_read_reg(SBC_SWK_STAT);
if( ((SYNC_MASK & registerReadOut) == SYNC_MASK)
&& ((SWK_SET_MASK & registerReadOut) == SWK_SET_MASK)
&& ((WUP_MASK & registerReadOut) != WUP_MASK)
&& ((WUF_MASK & registerReadOut) != WUF_MASK)) {
/* Empty */
} else {
errCode.SBC_Register = SBC_SWK_STAT;
errCode.expectedValue = 0b01000100U;
errCode.flippedBitsMask = errCode.expectedValue ^ registerReadOut;
return errCode;
}
}
/* Clear Wake Status Registers, so that SBC can sleep. */
errCode = sbc_write_reg(SBC_WK_STAT_1, 0x00, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg(SBC_WK_STAT_2, 0x00, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
/* Select sleep mode */
sbc_write_reg_field(SBC_M_S_CTRL, MODE_MASK, SBC_SLEEP_MODE, NULL);
errCode.SBC_Register = 0x00U;
errCode.flippedBitsMask = 0x00U;
errCode.expectedValue = 0x00U;
return errCode;
}
/* configure HSx */
SBC_ErrorCode sbc_hsx_config(sbc_hsx_t hsX, sbc_hs_config_t hsConfig) {
SBC_ErrorCode errCode = {0,0,0};
switch (hsX) {
case HS1:
errCode = sbc_write_reg_field(SBC_HS_CTRL_1, HS1_MASK, hsConfig, NULL);
break;
case HS2:
errCode = sbc_write_reg_field(SBC_HS_CTRL_1, HS2_MASK, hsConfig, NULL);
break;
case HS3:
errCode = sbc_write_reg_field(SBC_HS_CTRL_2, HS3_MASK, hsConfig, NULL);
break;
case HS4:
errCode = sbc_write_reg_field(SBC_HS_CTRL_2, HS4_MASK, hsConfig, NULL);
break;
default:
return errCode;
}
return errCode;
}
/* CAN MODE*/
SBC_ErrorCode sbc_can_mode(sbc_can_t CANmode )
{
SBC_ErrorCode errCode;
errCode = sbc_write_reg_field(SBC_BUS_CTRL_1, CAN_MASK, CANmode, NULL);
return errCode;
}
/* LIN MODE */
SBC_ErrorCode sbc_lin_mode(sbc_lin_module_t linModule, sbc_lin_mode_t linMode) {
SBC_ErrorCode errCode = {0,0,0};
uint8_t mr_sbc_variant = sbc_read_reg(SBC_FAM_PROD_STAT) & PROD_MASK;
/* check if it is a variant with minimum 1 LIN interface*/
if (mr_sbc_variant & 0b1000) {
if (linModule == LIN1) {
errCode = sbc_write_reg_field(SBC_BUS_CTRL_1, LIN1_MASK, linMode, NULL);
} else {
/* cheack if it is a variant with 2 LIN interfaces*/
if (mr_sbc_variant & 0b1100) {
errCode = sbc_write_reg_field(SBC_BUS_CTRL_2, LIN2_MASK, linMode, NULL);
} else {
return errCode; // default value 0
}
}
} else {
return errCode; // default value 0
}
return errCode;
}
/* WRITE IN System status register*/
SBC_ErrorCode sbc_sys_stat_write(uint8_t status) {
return sbc_write_reg(SBC_SYS_STAT_CTRL, status, NULL);
}
/* Read register system status*/
uint8_t sbc_sys_stat_read(void) {
return sbc_read_reg(SBC_SYS_STAT_CTRL);
}
// disabling WD and entering stop mode
SBC_ErrorCode sbc_mode_stop_without_watchdog(void) {
SBC_ErrorCode errCode = sbc_write_reg_field(SBC_WK_CTRL_1, WD_STM_EN_1_MASK, WATCHDOG_DEACTIVED_IN_STOP_MODE, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_WD_CTRL, WD_STM_EN_0_MASK, WATCHDOG_DEACTIVED_IN_STOP_MODE, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
return sbc_mode_stop();
}
/* configure cyclic sense function*/
SBC_ErrorCode sbc_cyclicsense(sbc_timer_t timer, sbc_timer_per_t timerPeriod, sbc_timer_on_t timerOnTime, sbc_hsx_t hsX, sbc_wk_t wk, sbc_wk_pupd_t pupdConfig) {
SBC_ErrorCode errCode={0,0,0};
if (timer == TIMER1) {
errCode = sbc_write_reg_field(SBC_TIMER1_CTRL, TIMER1_ON_MASK, TIMER_ONTIME_OFF_LOW, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
switch (hsX)
{
case HS1:
errCode = sbc_write_reg_field(SBC_HS_CTRL_1, HS1_MASK, CONTROLLED_BY_TIMER1, NULL);
break;
case HS2:
errCode = sbc_write_reg_field(SBC_HS_CTRL_1, HS2_MASK, CONTROLLED_BY_TIMER1, NULL);
break;
case HS3:
errCode = sbc_write_reg_field(SBC_HS_CTRL_2, HS3_MASK, CONTROLLED_BY_TIMER1, NULL);
break;
case HS4:
errCode = sbc_write_reg_field(SBC_HS_CTRL_2, HS4_MASK, CONTROLLED_BY_TIMER1, NULL);
break;
default:
return errCode;
}
if(errCode.flippedBitsMask > 0){
return errCode;
}
switch (wk) {
case WK1:
errCode = sbc_write_reg_field(SBC_WK_FLT_CTRL, WK1_FLT_MASK, FILTER_ONTIME_END_TIMER1, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_WK_PUPD_CTRL, WK1_PUPD_MASK, pupdConfig, NULL);
break;
case WK2:
errCode = sbc_write_reg_field(SBC_WK_FLT_CTRL, WK2_FLT_MASK, FILTER_ONTIME_END_TIMER1, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_WK_PUPD_CTRL, WK2_PUPD_MASK, pupdConfig, NULL);
break;
case WK3:
errCode = sbc_write_reg_field(SBC_WK_FLT_CTRL, WK3_FLT_MASK, FILTER_ONTIME_END_TIMER1, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_WK_PUPD_CTRL, WK3_PUPD_MASK, pupdConfig, NULL);
break;
default:
break;
}
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_TIMER1_CTRL, TIMER1_PER_MASK, timerPeriod, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_TIMER1_CTRL, TIMER1_ON_MASK, timerOnTime, NULL);
}
else if (timer == TIMER2)
{
errCode = sbc_write_reg_field(SBC_TIMER2_CTRL, TIMER2_ON_MASK, TIMER_ONTIME_OFF_LOW, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
switch (hsX) {
case HS1:
errCode = sbc_write_reg_field(SBC_HS_CTRL_1, HS1_MASK, CONTROLLED_BY_TIMER2, NULL);
break;
case HS2:
errCode = sbc_write_reg_field(SBC_HS_CTRL_1, HS2_MASK, CONTROLLED_BY_TIMER2, NULL);
break;
case HS3:
errCode = sbc_write_reg_field(SBC_HS_CTRL_2, HS3_MASK, CONTROLLED_BY_TIMER2, NULL);
break;
case HS4:
errCode = sbc_write_reg_field(SBC_HS_CTRL_2, HS4_MASK, CONTROLLED_BY_TIMER2, NULL);
break;
default:
return errCode;
}
if(errCode.flippedBitsMask > 0) {
return errCode;
}
switch (wk)
{
case WK1:
errCode = sbc_write_reg_field(SBC_WK_FLT_CTRL, WK1_FLT_MASK, FILTER_ONTIME_END_TIMER2, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_WK_PUPD_CTRL, WK1_PUPD_MASK, pupdConfig, NULL);
break;
case WK2:
errCode = sbc_write_reg_field(SBC_WK_FLT_CTRL, WK2_FLT_MASK, FILTER_ONTIME_END_TIMER2, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_WK_PUPD_CTRL, WK2_PUPD_MASK, pupdConfig, NULL);
break;
case WK3:
errCode = sbc_write_reg_field(SBC_WK_FLT_CTRL, WK3_FLT_MASK, FILTER_ONTIME_END_TIMER2, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_WK_PUPD_CTRL, WK3_PUPD_MASK, pupdConfig, NULL);
break;
default:
break;
}
errCode = sbc_write_reg_field(SBC_TIMER2_CTRL, TIMER2_PER_MASK, timerPeriod, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_TIMER2_CTRL, TIMER2_ON_MASK, timerOnTime, NULL);
} else {
return errCode;
}
return errCode;
}
/* configure cyclic wake function*/
SBC_ErrorCode sbc_cyclicwake(sbc_timer_t timer, sbc_timer_per_t timer_period, sbc_timer_on_t timer_on_time) {
SBC_ErrorCode errCode={0,0,0};
if (timer == TIMER1) {
errCode = sbc_write_reg_field(SBC_WK_CTRL_1, TIMER1_WK_EN_MASK, TIMER_WAKE_DISABLED, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_TIMER1_CTRL, TIMER1_PER_MASK, timer_period, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_TIMER1_CTRL, TIMER1_ON_MASK, timer_on_time, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_WK_CTRL_1, TIMER1_WK_EN_MASK, TIMER_WAKE_ENABLED, NULL);
}
else if (timer == TIMER2) {
errCode = sbc_write_reg_field(SBC_WK_CTRL_1, TIMER2_WK_EN_MASK, TIMER_WAKE_DISABLED, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_TIMER2_CTRL, TIMER2_PER_MASK, timer_period, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_TIMER2_CTRL, TIMER2_ON_MASK, timer_on_time, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_WK_CTRL_1, TIMER2_WK_EN_MASK, TIMER_WAKE_ENABLED, NULL);
} else {
return errCode;
}
return errCode;
}
/* configure watchdog*/
SBC_ErrorCode sbc_configure_watchdog(sbc_wd_win_t wdWindow, sbc_wd_en_wk_bus_t wdEnableAfterBusWake, sbc_wd_timer_t wdTimer) {
SBC_ErrorCode errCode;
/* Calculate checksum */
uint8_t wd_ctrl = (wdWindow << SBC_BITPOSITION(WD_WIN_MASK))
| (wdEnableAfterBusWake << SBC_BITPOSITION(WD_EN_WK_BUS_MASK))
| (wdTimer << SBC_BITPOSITION(WD_TIMER_MASK));
uint8_t checksum = wd_ctrl;
checksum = checksum ^ checksum >> 4;
checksum = checksum ^ checksum >> 2;
checksum = checksum ^ checksum >> 1;
if((checksum & 1) > 0) {
/* Set parity bit */
wd_ctrl = wd_ctrl | 0x80U; //
}
errCode = sbc_write_reg(SBC_WD_CTRL, wd_ctrl, NULL);
if (errCode.flippedBitsMask == 0) {
/* Save new Watchdog configuration to global variable */
wd_config = wd_ctrl;
}
return errCode;
}
/* configure PWM*/
SBC_ErrorCode sbc_configure_pwm(sbc_pwm_t pwm, sbc_pwm_freq_t frequency, uint8_t dutyCycle) {
SBC_ErrorCode errCode={0,0,0};
switch (pwm) {
case PWM1:
errCode = sbc_write_reg(SBC_PWM1_CTRL, dutyCycle, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_PWM_FREQ_CTRL, PWM1_FREQ_MASK, frequency, NULL);
break;
case PWM2:
errCode = sbc_write_reg(SBC_PWM2_CTRL, dutyCycle, NULL);
if(errCode.flippedBitsMask > 0) {
return errCode;
}
errCode = sbc_write_reg_field(SBC_PWM_FREQ_CTRL, PWM2_FREQ_MASK, frequency, NULL);
break;
default:
return errCode;
}
return errCode;
}
/* configure PWM percentage*/
SBC_ErrorCode sbc_configure_pwm_percentage(sbc_pwm_t pwm, sbc_pwm_freq_t frequency, double duty_cycle) {
return sbc_configure_pwm(pwm, frequency, (uint8_t)(duty_cycle*0xFFU));
}
/* Configure GPIO*/
SBC_ErrorCode sbc_configure_gpio(sbc_gpiox_t gpio, sbc_gpio_t gpio_config) {
SBC_ErrorCode errCode= {0,0,0};
switch (gpio) {
case GPIO1:
errCode = sbc_write_reg_field(SBC_GPIO_CTRL, GPIO1_MASK, gpio_config, NULL);
break;
case GPIO2:
errCode = sbc_write_reg_field(SBC_GPIO_CTRL, GPIO2_MASK, gpio_config, NULL);
break;
default:
return errCode;
}
return errCode;
}
/* Configure Failure Output*/
SBC_ErrorCode sbc_fo_x(uint8_t on) {
if (on) {
return sbc_write_reg_field(SBC_HW_CTRL, FO_ON_MASK, FO_ON_ACTIVE, NULL);
} else {
return sbc_write_reg_field(SBC_HW_CTRL, FO_ON_MASK, FO_ON_NOT_ACTIVE, NULL);
}
}
/* configure VCC2*/
SBC_ErrorCode sbc_switch_vcc2(sbc_vcc2_on_t vcc2_value) {
SBC_ErrorCode errCode;
errCode = sbc_write_reg_field(SBC_M_S_CTRL, VCC2_ON_MASK, vcc2_value, NULL);
return errCode;
}
/* configure VCC3*/
SBC_ErrorCode sbc_switch_vcc3(sbc_vcc3_on_t vcc3_value) {
SBC_ErrorCode errCode;
errCode = sbc_write_reg_field(SBC_M_S_CTRL, VCC3_ON_MASK , vcc3_value, NULL);
return errCode;
}