openpilot v0.9.6 release
date: 2024-01-12T10:13:37 master commit: ba792d576a49a0899b88a753fa1c52956bedf9e6
This commit is contained in:
69
body/board/drivers/angle_sensor.h
Normal file
69
body/board/drivers/angle_sensor.h
Normal file
@@ -0,0 +1,69 @@
|
||||
// Default addresses for AS5048B
|
||||
#define AS5048_ADDRESS_LEFT 0x40
|
||||
#define AS5048_ADDRESS_RIGHT 0x41
|
||||
#define UNKNOWN_IMU 0x68
|
||||
|
||||
#define AS5048B_PROG_REG 0x03
|
||||
#define AS5048B_ADDR_REG 0x15
|
||||
#define AS5048B_ZEROMSB_REG 0x16 //bits 0..7
|
||||
#define AS5048B_ZEROLSB_REG 0x17 //bits 0..5
|
||||
#define AS5048B_GAIN_REG 0xFA
|
||||
#define AS5048B_DIAG_REG 0xFB
|
||||
#define AS5048B_MAGNMSB_REG 0xFC //bits 0..7
|
||||
#define AS5048B_MAGNLSB_REG 0xFD //bits 0..5
|
||||
#define AS5048B_ANGLMSB_REG 0xFE //bits 0..7
|
||||
#define AS5048B_ANGLLSB_REG 0xFF //bits 0..5
|
||||
|
||||
extern I2C_HandleTypeDef hi2c1;
|
||||
|
||||
const uint8_t init_imu_regaddr[] = {0x76, 0x4c, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53};
|
||||
const uint8_t init_imu_data[] = {0x00, 0x12, 0x2f, 0x26, 0x67, 0x04, 0x00, 0x00};
|
||||
|
||||
fault_status_t fault_status = {0};
|
||||
|
||||
void angle_sensor_read(uint16_t *sensor_angle) {
|
||||
|
||||
if (fault_status.left_i2c && fault_status.right_i2c) { // Try to reinitialize halted I2C
|
||||
if (HAL_I2C_Init(&hi2c1) == HAL_OK) {
|
||||
fault_status.left_i2c = 0;
|
||||
fault_status.right_i2c = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t buf[2];
|
||||
if (HAL_I2C_Mem_Read(&hi2c1, (AS5048_ADDRESS_LEFT<<1), AS5048B_ANGLMSB_REG, I2C_MEMADD_SIZE_8BIT, buf, 2, 10) == HAL_OK) {
|
||||
sensor_angle[0] = (buf[0] << 6) | (buf[1] & 0x3F);
|
||||
fault_status.left_i2c = 0;
|
||||
} else {
|
||||
fault_status.left_i2c = 1;
|
||||
}
|
||||
if (HAL_I2C_Mem_Read(&hi2c1, (AS5048_ADDRESS_RIGHT<<1), AS5048B_ANGLMSB_REG, I2C_MEMADD_SIZE_8BIT, buf, 2, 10) == HAL_OK) {
|
||||
sensor_angle[1] = (buf[0] << 6) | (buf[1] & 0x3F);
|
||||
fault_status.right_i2c = 0;
|
||||
} else {
|
||||
fault_status.right_i2c = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void IMU_soft_init(void) {
|
||||
i2c_port_init();
|
||||
|
||||
for (int8_t i = 3; i > 0; i--) {
|
||||
SW_I2C_WriteControl_8Bit((UNKNOWN_IMU<<1), 0x75, 0x00);
|
||||
}
|
||||
for (int8_t i = sizeof(init_imu_regaddr)-1; i >= 0; i--) {
|
||||
SW_I2C_WriteControl_8Bit((UNKNOWN_IMU<<1), init_imu_regaddr[i], init_imu_data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void IMU_soft_sensor_read(uint16_t *unknown_imu_data) {
|
||||
static uint8_t buf[12];
|
||||
|
||||
SW_I2C_WriteControl_8Bit((UNKNOWN_IMU<<1), 0x76, 0x00);
|
||||
SW_I2C_Multi_ReadnControl_8Bit((UNKNOWN_IMU<<1), 0x1F, 6, buf);
|
||||
SW_I2C_Multi_ReadnControl_8Bit((UNKNOWN_IMU<<1), 0x25, 6, &buf[6]);
|
||||
|
||||
for (int8_t i = 5; i >= 0; i--) {
|
||||
unknown_imu_data[i] = (buf[i*2] << 8) | (buf[(i*2)+1]);
|
||||
}
|
||||
}
|
||||
63
body/board/drivers/clock.h
Normal file
63
body/board/drivers/clock.h
Normal file
@@ -0,0 +1,63 @@
|
||||
void Error_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN Error_Handler_Debug */
|
||||
/* User can add his own implementation to report the HAL error return state */
|
||||
__disable_irq();
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
/* USER CODE END Error_Handler_Debug */
|
||||
}
|
||||
/** System Clock Configuration
|
||||
*/
|
||||
void SystemClock_Config(void) {
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct;
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct;
|
||||
|
||||
/** Configure the main internal regulator output voltage
|
||||
*/
|
||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
||||
|
||||
/**Initializes the CPU, AHB and APB busses clocks
|
||||
*/
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
|
||||
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
|
||||
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
|
||||
|
||||
RCC_OscInitStruct.PLL.PLLM = 8;
|
||||
RCC_OscInitStruct.PLL.PLLN = 96; // Gives 96 Mhz core clock
|
||||
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 2;
|
||||
RCC_OscInitStruct.PLL.PLLR = 2;
|
||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/**Initializes the CPU, AHB and APB busses clocks
|
||||
*/
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|
||||
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
||||
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/**Configure the Systick interrupt time
|
||||
*/
|
||||
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000);
|
||||
|
||||
/**Configure the Systick
|
||||
*/
|
||||
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
|
||||
|
||||
/* SysTick_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
|
||||
}
|
||||
305
body/board/drivers/i2c_soft.h
Normal file
305
body/board/drivers/i2c_soft.h
Normal file
@@ -0,0 +1,305 @@
|
||||
#define SW_I2C_WAIT_TIME 22
|
||||
|
||||
#define I2C_READ 0x01
|
||||
#define READ_CMD 1
|
||||
#define WRITE_CMD 0
|
||||
|
||||
|
||||
void SW_I2C_init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure = { 0 };
|
||||
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
|
||||
GPIO_InitStructure.Pin = SW_I2C1_SCL_PIN;
|
||||
HAL_GPIO_Init(SW_I2C1_SCL_GPIO, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.Pin = SW_I2C1_SDA_PIN;
|
||||
HAL_GPIO_Init(SW_I2C1_SDA_GPIO, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
uint8_t SW_I2C_ReadVal_SDA(void)
|
||||
{
|
||||
uint8_t ret;
|
||||
ret = (uint16_t)HAL_GPIO_ReadPin(SW_I2C1_SDA_GPIO, SW_I2C1_SDA_PIN);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sda_high(void)
|
||||
{
|
||||
HAL_GPIO_WritePin(SW_I2C1_SDA_GPIO, SW_I2C1_SDA_PIN, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
|
||||
void sda_low(void)
|
||||
{
|
||||
HAL_GPIO_WritePin(SW_I2C1_SDA_GPIO, SW_I2C1_SDA_PIN, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
|
||||
void scl_high(void)
|
||||
{
|
||||
HAL_GPIO_WritePin(SW_I2C1_SCL_GPIO, SW_I2C1_SCL_PIN, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
|
||||
void scl_low(void)
|
||||
{
|
||||
HAL_GPIO_WritePin(SW_I2C1_SCL_GPIO, SW_I2C1_SCL_PIN, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
void sda_out(uint8_t out)
|
||||
{
|
||||
if (out) {
|
||||
sda_high();
|
||||
} else {
|
||||
sda_low();
|
||||
}
|
||||
}
|
||||
|
||||
void sda_in_mode(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure = { 0 };
|
||||
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
|
||||
|
||||
GPIO_InitStructure.Pin = SW_I2C1_SDA_PIN;
|
||||
HAL_GPIO_Init(SW_I2C1_SDA_GPIO, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
void sda_out_mode(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure = { 0 };
|
||||
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
|
||||
|
||||
GPIO_InitStructure.Pin = SW_I2C1_SDA_PIN;
|
||||
HAL_GPIO_Init(SW_I2C1_SDA_GPIO, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
void i2c_clk_data_out(void)
|
||||
{
|
||||
scl_high();
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
scl_low();
|
||||
}
|
||||
|
||||
void i2c_port_init(void)
|
||||
{
|
||||
sda_high();
|
||||
scl_high();
|
||||
}
|
||||
|
||||
void i2c_start_condition(void)
|
||||
{
|
||||
sda_high();
|
||||
scl_high();
|
||||
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
sda_low();
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
scl_low();
|
||||
|
||||
delay(SW_I2C_WAIT_TIME << 1);
|
||||
}
|
||||
|
||||
void i2c_stop_condition(void)
|
||||
{
|
||||
sda_low();
|
||||
scl_high();
|
||||
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
sda_high();
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
}
|
||||
|
||||
uint8_t i2c_check_ack(void)
|
||||
{
|
||||
uint8_t ack;
|
||||
int i;
|
||||
unsigned int temp;
|
||||
|
||||
sda_in_mode();
|
||||
|
||||
scl_high();
|
||||
|
||||
ack = 0;
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
|
||||
for (i = 10; i > 0; i--) {
|
||||
temp = !(SW_I2C_ReadVal_SDA());
|
||||
if (temp)
|
||||
{
|
||||
ack = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
scl_low();
|
||||
sda_out_mode();
|
||||
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
return ack;
|
||||
}
|
||||
|
||||
void i2c_check_not_ack(void)
|
||||
{
|
||||
sda_in_mode();
|
||||
i2c_clk_data_out();
|
||||
sda_out_mode();
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
}
|
||||
|
||||
void i2c_slave_address(uint8_t IICID, uint8_t readwrite)
|
||||
{
|
||||
int x;
|
||||
|
||||
if (readwrite) {
|
||||
IICID |= I2C_READ;
|
||||
} else {
|
||||
IICID &= ~I2C_READ;
|
||||
}
|
||||
|
||||
scl_low();
|
||||
|
||||
for (x = 7; x >= 0; x--) {
|
||||
sda_out(IICID & (1 << x));
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
i2c_clk_data_out();
|
||||
}
|
||||
}
|
||||
|
||||
void i2c_register_address(uint8_t addr)
|
||||
{
|
||||
int x;
|
||||
|
||||
scl_low();
|
||||
|
||||
for (x = 7; x >= 0; x--) {
|
||||
sda_out(addr & (1 << x));
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
i2c_clk_data_out();
|
||||
}
|
||||
}
|
||||
|
||||
void i2c_send_ack(void)
|
||||
{
|
||||
sda_out_mode();
|
||||
sda_low();
|
||||
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
scl_high();
|
||||
|
||||
delay(SW_I2C_WAIT_TIME << 1);
|
||||
|
||||
sda_low();
|
||||
delay(SW_I2C_WAIT_TIME << 1);
|
||||
|
||||
scl_low();
|
||||
|
||||
sda_out_mode();
|
||||
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
}
|
||||
|
||||
void SW_I2C_Write_Data(uint8_t data)
|
||||
{
|
||||
int x;
|
||||
|
||||
scl_low();
|
||||
|
||||
for (x = 7; x >= 0; x--) {
|
||||
sda_out(data & (1 << x));
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
i2c_clk_data_out();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SW_I2C_Read_Data(void)
|
||||
{
|
||||
int x;
|
||||
uint8_t readdata = 0;
|
||||
|
||||
sda_in_mode();
|
||||
|
||||
for (x = 8; x--;) {
|
||||
scl_high();
|
||||
|
||||
readdata <<= 1;
|
||||
if (SW_I2C_ReadVal_SDA()) { readdata |= 0x01; }
|
||||
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
scl_low();
|
||||
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
}
|
||||
|
||||
sda_out_mode();
|
||||
return readdata;
|
||||
}
|
||||
|
||||
uint8_t SW_I2C_WriteControl_8Bit(uint8_t IICID, uint8_t regaddr, uint8_t data)
|
||||
{
|
||||
uint8_t returnack = true;
|
||||
|
||||
i2c_start_condition();
|
||||
|
||||
i2c_slave_address(IICID, WRITE_CMD);
|
||||
if (!i2c_check_ack()) { returnack = false; }
|
||||
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
|
||||
i2c_register_address(regaddr);
|
||||
if (!i2c_check_ack()) { returnack = false; }
|
||||
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
|
||||
SW_I2C_Write_Data(data);
|
||||
if (!i2c_check_ack()) { returnack = false; }
|
||||
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
|
||||
i2c_stop_condition();
|
||||
|
||||
return returnack;
|
||||
}
|
||||
|
||||
uint8_t SW_I2C_Multi_ReadnControl_8Bit(uint8_t IICID, uint8_t regaddr, uint8_t rcnt, uint8_t (*pdata))
|
||||
{
|
||||
uint8_t returnack = true;
|
||||
uint8_t index;
|
||||
|
||||
i2c_port_init();
|
||||
|
||||
i2c_start_condition();
|
||||
|
||||
i2c_slave_address(IICID, WRITE_CMD);
|
||||
if (!i2c_check_ack()) { returnack = false; }
|
||||
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
|
||||
i2c_register_address(regaddr);
|
||||
if (!i2c_check_ack()) { returnack = false; }
|
||||
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
|
||||
i2c_start_condition();
|
||||
|
||||
i2c_slave_address(IICID, READ_CMD);
|
||||
if (!i2c_check_ack()) { returnack = false; }
|
||||
|
||||
for ( index = 0 ; index < (rcnt-1) ; index++) {
|
||||
delay(SW_I2C_WAIT_TIME);
|
||||
pdata[index] = SW_I2C_Read_Data();
|
||||
i2c_send_ack();
|
||||
}
|
||||
|
||||
pdata[rcnt-1] = SW_I2C_Read_Data();
|
||||
|
||||
i2c_check_not_ack();
|
||||
|
||||
i2c_stop_condition();
|
||||
|
||||
return returnack;
|
||||
}
|
||||
125
body/board/drivers/llbxcan.h
Normal file
125
body/board/drivers/llbxcan.h
Normal file
@@ -0,0 +1,125 @@
|
||||
// SAE 2284-3 : minimum 16 tq, SJW 3, sample point at 81.3%
|
||||
#define CAN_QUANTA 16U
|
||||
#define CAN_SEQ1 12U
|
||||
#define CAN_SEQ2 3U
|
||||
#define CAN_SJW 3U
|
||||
|
||||
#define CAN_PCLK (CORE_FREQ / 2U / 1000U)
|
||||
#define can_speed_to_prescaler(x) (CAN_PCLK / CAN_QUANTA * 10U / (x))
|
||||
#define CAN_INIT_TIMEOUT_MS 500
|
||||
|
||||
bool llcan_set_speed(CAN_TypeDef *CAN_obj, uint32_t speed, bool loopback, bool silent) {
|
||||
bool ret = true;
|
||||
|
||||
// initialization mode
|
||||
CAN1->MCR = CAN_MCR_INRQ; // When we want to use only CAN2 - need to do that
|
||||
CAN_obj->MCR = CAN_MCR_INRQ;
|
||||
uint32_t timeout_counter = 0U;
|
||||
while((CAN_obj->MSR & CAN_MSR_INAK) != CAN_MSR_INAK){
|
||||
// Delay for about 1ms
|
||||
delay(10000);
|
||||
timeout_counter++;
|
||||
|
||||
if(timeout_counter >= CAN_INIT_TIMEOUT_MS){
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret){
|
||||
// set time quanta from defines
|
||||
CAN_obj->BTR = ((CAN_BTR_TS1_0 * (CAN_SEQ1-1)) |
|
||||
(CAN_BTR_TS2_0 * (CAN_SEQ2-1)) |
|
||||
(CAN_BTR_SJW_0 * (CAN_SJW-1)) |
|
||||
(can_speed_to_prescaler(speed) - 1U));
|
||||
|
||||
// silent loopback mode for debugging
|
||||
if (loopback) {
|
||||
CAN_obj->BTR |= CAN_BTR_SILM | CAN_BTR_LBKM;
|
||||
}
|
||||
if (silent) {
|
||||
CAN_obj->BTR |= CAN_BTR_SILM;
|
||||
}
|
||||
|
||||
CAN_obj->MCR |= CAN_MCR_AWUM; // Automatic wakeup mode
|
||||
CAN_obj->MCR |= CAN_MCR_ABOM; // Automatic bus-off management
|
||||
CAN_obj->MCR &= ~CAN_MCR_NART; // Automatic retransmission
|
||||
CAN_obj->MCR |= CAN_MCR_TXFP; // Priority driven by the request order (chronologically)
|
||||
CAN_obj->MCR &= ~CAN_MCR_INRQ;
|
||||
|
||||
timeout_counter = 0U;
|
||||
while(((CAN_obj->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)) {
|
||||
// Delay for about 1ms
|
||||
delay(10000);
|
||||
timeout_counter++;
|
||||
|
||||
if(timeout_counter >= CAN_INIT_TIMEOUT_MS){
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool llcan_init(CAN_TypeDef *CAN_obj) {
|
||||
bool ret = true;
|
||||
|
||||
// Enter init mode
|
||||
CAN_obj->FMR |= CAN_FMR_FINIT;
|
||||
|
||||
// Wait for INAK bit to be set
|
||||
uint32_t timeout_counter = 0U;
|
||||
while(((CAN_obj->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)) {
|
||||
// Delay for about 1ms
|
||||
delay(10000);
|
||||
timeout_counter++;
|
||||
|
||||
if(timeout_counter >= CAN_INIT_TIMEOUT_MS){
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret){
|
||||
// no mask
|
||||
// For some weird reason some of these registers do not want to set properly on CAN2 and CAN3. Probably something to do with the single/dual mode and their different filters.
|
||||
// Filters MUST be set always through CAN1(Master) as CAN2/3 are Slave
|
||||
CAN1->sFilterRegister[0].FR1 = 0U;
|
||||
CAN1->sFilterRegister[0].FR2 = 0U;
|
||||
CAN1->sFilterRegister[14].FR1 = 0U;
|
||||
CAN1->sFilterRegister[14].FR2 = 0U;
|
||||
CAN1->FA1R |= 1U | (1U << 14);
|
||||
|
||||
// Exit init mode, do not wait
|
||||
CAN_obj->FMR &= ~CAN_FMR_FINIT;
|
||||
|
||||
// enable certain CAN interrupts
|
||||
CAN1->IER = 0U; // When we want to use only CAN2 - need to do that
|
||||
CAN_obj->IER = CAN_IER_FMPIE0 | CAN_IER_TMEIE | CAN_IER_WKUIE;
|
||||
|
||||
if (CAN_obj == CAN1) {
|
||||
HAL_NVIC_EnableIRQ(CAN1_TX_IRQn);
|
||||
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
|
||||
HAL_NVIC_SetPriority(CAN1_SCE_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(CAN1_SCE_IRQn);
|
||||
} else {
|
||||
HAL_NVIC_SetPriority(CAN2_TX_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(CAN2_TX_IRQn);
|
||||
HAL_NVIC_SetPriority(CAN2_RX0_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(CAN2_RX0_IRQn);
|
||||
HAL_NVIC_SetPriority(CAN2_SCE_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(CAN2_SCE_IRQn);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void llcan_clear_send(CAN_TypeDef *CAN_obj) {
|
||||
CAN_obj->TSR |= CAN_TSR_ABRQ0;
|
||||
CAN_obj->MSR &= ~CAN_MSR_ERRI;
|
||||
// cppcheck-suppress selfAssignment ; needed to clear the register
|
||||
CAN_obj->MSR = CAN_obj->MSR;
|
||||
}
|
||||
26
body/board/drivers/llflash.h
Normal file
26
body/board/drivers/llflash.h
Normal file
@@ -0,0 +1,26 @@
|
||||
bool flash_is_locked(void) {
|
||||
return (FLASH->CR & FLASH_CR_LOCK);
|
||||
}
|
||||
|
||||
void flash_unlock(void) {
|
||||
FLASH->KEYR = 0x45670123;
|
||||
FLASH->KEYR = 0xCDEF89AB;
|
||||
}
|
||||
|
||||
bool flash_erase_sector(uint8_t sector, bool unlocked) {
|
||||
// don't erase the bootloader(sector 0)
|
||||
if (sector != 0 && sector < 12 && unlocked) {
|
||||
FLASH->CR = (sector << 3) | FLASH_CR_SER;
|
||||
FLASH->CR |= FLASH_CR_STRT;
|
||||
while (FLASH->SR & FLASH_SR_BSY);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void flash_write_word(void *prog_ptr, uint32_t data) {
|
||||
uint32_t *pp = prog_ptr;
|
||||
FLASH->CR = FLASH_CR_PSIZE_1 | FLASH_CR_PG;
|
||||
*pp = data;
|
||||
while (FLASH->SR & FLASH_SR_BSY);
|
||||
}
|
||||
Reference in New Issue
Block a user