Add full automotive RTOS project
Add kernel (Cortex-M0/M3/M4, Tricore, S32K, RISC-V ports), drivers, middleware (CAN stack, diagnostics, safety), applications, board support, build/test tooling, and documentation.
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @file tc3xx_config.h
|
||||
* @brief Infineon TriCore TC3xx specific configuration
|
||||
*/
|
||||
|
||||
#ifndef TC3XX_CONFIG_H
|
||||
#define TC3XX_CONFIG_H
|
||||
|
||||
/* MCU Specific Definitions */
|
||||
#define TC397
|
||||
#define CPU_FREQUENCY 300000000U /* 300 MHz */
|
||||
#define PERIPHERAL_FREQUENCY 150000000U /* 150 MHz */
|
||||
#define STM_FREQUENCY 100000000U /* 100 MHz */
|
||||
|
||||
/* Peripheral Base Addresses */
|
||||
#define CAN0_BASE 0xF0200000U
|
||||
#define CAN1_BASE 0xF0210000U
|
||||
#define CAN2_BASE 0xF0220000U
|
||||
#define CAN3_BASE 0xF0230000U
|
||||
|
||||
#define ASCLIN0_BASE 0xF0000000U
|
||||
#define ASCLIN1_BASE 0xF0000100U
|
||||
#define ASCLIN2_BASE 0xF0000200U
|
||||
#define ASCLIN3_BASE 0xF0000300U
|
||||
|
||||
#define QSPI0_BASE 0xF0001000U
|
||||
#define QSPI1_BASE 0xF0001100U
|
||||
#define QSPI2_BASE 0xF0001200U
|
||||
#define QSPI3_BASE 0xF0001300U
|
||||
|
||||
#define I2C0_BASE 0xF0002000U
|
||||
#define I2C1_BASE 0xF0002100U
|
||||
|
||||
#define VADC0_BASE 0xF0020000U
|
||||
#define VADC1_BASE 0xF0020100U
|
||||
|
||||
#define GTM_BASE 0xF0100000U
|
||||
#define GPT12_BASE 0xF0003000U
|
||||
|
||||
/* Interrupt Priorities */
|
||||
#define CAN0_IRQ_PRIORITY 5
|
||||
#define CAN1_IRQ_PRIORITY 5
|
||||
#define ASCLIN0_IRQ_PRIORITY 6
|
||||
#define QSPI0_IRQ_PRIORITY 7
|
||||
#define I2C0_IRQ_PRIORITY 7
|
||||
#define VADC0_IRQ_PRIORITY 8
|
||||
#define GTM_IRQ_PRIORITY 8
|
||||
|
||||
/* DMA Configuration */
|
||||
#define DMA_CHANNEL_COUNT 128
|
||||
#define DMA_PRIORITY_HIGH 0
|
||||
#define DMA_PRIORITY_MEDIUM 1
|
||||
#define DMA_PRIORITY_LOW 2
|
||||
|
||||
/* Safety Features */
|
||||
#define ENABLE_SAFETY_WATCHDOG 1
|
||||
#define WATCHDOG_TIMEOUT_MS 100
|
||||
#define ENABLE_ECC 1
|
||||
#define ENABLE_MEMORY_PROTECTION 1
|
||||
|
||||
/* Memory Configuration */
|
||||
#define FLASH_SIZE 0x800000U /* 8 MB */
|
||||
#define RAM_SIZE 0x280000U /* 2.5 MB */
|
||||
#define DSPR_SIZE 0x20000U /* 128 KB per CPU */
|
||||
|
||||
/* CAN FD Configuration */
|
||||
#define CAN_FD_ENABLED 1
|
||||
#define CAN_FD_MAX_PAYLOAD 64
|
||||
#define CAN_TX_FIFO_SIZE 32
|
||||
#define CAN_RX_FIFO_SIZE 64
|
||||
|
||||
#endif /* TC3XX_CONFIG_H */
|
||||
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @file tc3xx_hal.c
|
||||
* @brief Infineon TriCore TC3xx Hardware Abstraction Layer
|
||||
*/
|
||||
|
||||
#include "tc3xx_config.h"
|
||||
#include "can_driver.h"
|
||||
#include "uart_driver.h"
|
||||
#include "spi_driver.h"
|
||||
#include "i2c_driver.h"
|
||||
#include "gpio_driver.h"
|
||||
#include "adc_driver.h"
|
||||
#include "pwm_driver.h"
|
||||
#include "Ifx_Types.h"
|
||||
#include "IfxCan_Can.h"
|
||||
#include "IfxAsclin_Asc.h"
|
||||
#include "IfxQspi_SpiMaster.h"
|
||||
#include "IfxI2c_I2c.h"
|
||||
#include "IfxPort.h"
|
||||
#include "IfxVadc_Adc.h"
|
||||
#include "IfxGtm_Tom_PwmHl.h"
|
||||
|
||||
/* CAN HAL Implementation */
|
||||
int hal_can_init(uint32_t baudrate, uint8_t frame_type, bool enable_fd) {
|
||||
/* Create CAN module configuration */
|
||||
IfxCan_Can_Config canConfig;
|
||||
IfxCan_Can_initModuleConfig(&canConfig, &MODULE_CAN0);
|
||||
|
||||
/* Configure node */
|
||||
canConfig.nodeConfig[0].baudRate.baudrate = baudrate;
|
||||
canConfig.nodeConfig[0].frame.type = IfxCan_FrameType_receive;
|
||||
|
||||
if (enable_fd) {
|
||||
canConfig.nodeConfig[0].frame.mode = IfxCan_FrameMode_fd;
|
||||
}
|
||||
|
||||
/* Initialize CAN module */
|
||||
IfxCan_Can_initModule(&g_canDriver, &canConfig);
|
||||
|
||||
/* Configure TX FIFO */
|
||||
IfxCan_Can_initTxFifo(&g_canDriver, &g_canTxFifo);
|
||||
|
||||
/* Configure RX FIFO */
|
||||
IfxCan_Can_initRxFifo(&g_canDriver, &g_canRxFifo);
|
||||
|
||||
/* Enable interrupts */
|
||||
IfxCan_Can_enableInterrupt(&g_canDriver, IfxCan_Interrupt_messageStoredToDedicatedRxFifo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hal_can_send_message(const CanMessage_t* message, uint32_t* mailbox) {
|
||||
/* Create TX message */
|
||||
IfxCan_Can_Message txMessage;
|
||||
|
||||
/* Set message ID */
|
||||
txMessage.messageId = message->id.id;
|
||||
txMessage.extendedFrame = message->id.is_extended;
|
||||
|
||||
/* Set data */
|
||||
txMessage.dataLengthCode = message->length;
|
||||
for (int i = 0; i < message->length; i++) {
|
||||
txMessage.data[i] = message->data[i];
|
||||
}
|
||||
|
||||
/* Send message */
|
||||
if (IfxCan_Can_sendMessage(&g_canDriver, &txMessage, &txMessage.messageId)
|
||||
!= IfxCan_Status_ok) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*mailbox = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hal_can_receive_message(CanMessage_t* message) {
|
||||
/* Create RX message */
|
||||
IfxCan_Can_Message rxMessage;
|
||||
|
||||
/* Receive message */
|
||||
if (IfxCan_Can_readMessage(&g_canDriver, &rxMessage, &rxMessage.messageId)
|
||||
!= IfxCan_Status_ok) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy message data */
|
||||
message->id.id = rxMessage.messageId;
|
||||
message->id.is_extended = rxMessage.extendedFrame;
|
||||
message->length = rxMessage.dataLengthCode;
|
||||
|
||||
for (int i = 0; i < message->length; i++) {
|
||||
message->data[i] = rxMessage.data[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* GPIO HAL Implementation */
|
||||
void hal_gpio_init(uint8_t port, uint8_t pin, GpioMode_t mode) {
|
||||
/* Configure port pin */
|
||||
IfxPort_setPinMode(&MODULE_P00, pin, IfxPort_Mode_outputPushPullGeneral);
|
||||
}
|
||||
|
||||
void hal_gpio_write(uint8_t port, uint8_t pin, bool value) {
|
||||
if (value) {
|
||||
IfxPort_setPinHigh(&MODULE_P00, pin);
|
||||
} else {
|
||||
IfxPort_setPinLow(&MODULE_P00, pin);
|
||||
}
|
||||
}
|
||||
|
||||
bool hal_gpio_read(uint8_t port, uint8_t pin) {
|
||||
return IfxPort_getPinState(&MODULE_P00, pin);
|
||||
}
|
||||
|
||||
/* UART HAL Implementation */
|
||||
int hal_uart_init(uint8_t instance, UartConfig_t* config) {
|
||||
/* Create ASCLIN configuration */
|
||||
IfxAsclin_Asc_Config ascConfig;
|
||||
IfxAsclin_Asc_initModuleConfig(&ascConfig, &MODULE_ASCLIN0);
|
||||
|
||||
/* Configure baudrate */
|
||||
ascConfig.baudrate.baudrate = config->baudrate;
|
||||
|
||||
/* Configure pins */
|
||||
ascConfig.pins = &g_ascPins;
|
||||
|
||||
/* Initialize module */
|
||||
IfxAsclin_Asc_initModule(&g_ascDriver, &ascConfig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @file s32k14x_config.h
|
||||
* @brief NXP S32K14x specific configuration
|
||||
*/
|
||||
|
||||
#ifndef S32K14X_CONFIG_H
|
||||
#define S32K14X_CONFIG_H
|
||||
|
||||
/* MCU Specific Definitions */
|
||||
#define S32K144
|
||||
#define CPU_FREQUENCY 160000000U /* 160 MHz */
|
||||
#define BUS_FREQUENCY 40000000U /* 40 MHz */
|
||||
#define SLOW_FREQUENCY 10000000U /* 10 MHz */
|
||||
|
||||
/* Peripheral Base Addresses */
|
||||
#define GPIOA_BASE 0x400FF000U
|
||||
#define GPIOB_BASE 0x400FF040U
|
||||
#define GPIOC_BASE 0x400FF080U
|
||||
#define GPIOD_BASE 0x400FF0C0U
|
||||
#define GPIOE_BASE 0x400FF100U
|
||||
|
||||
#define LPUART0_BASE 0x4006A000U
|
||||
#define LPUART1_BASE 0x4006B000U
|
||||
#define LPUART2_BASE 0x4006C000U
|
||||
|
||||
#define LPSPI0_BASE 0x4002C000U
|
||||
#define LPSPI1_BASE 0x4002D000U
|
||||
#define LPSPI2_BASE 0x4002E000U
|
||||
|
||||
#define LPI2C0_BASE 0x40066000U
|
||||
#define LPI2C1_BASE 0x40067000U
|
||||
|
||||
#define ADC0_BASE 0x4003B000U
|
||||
#define ADC1_BASE 0x4003C000U
|
||||
|
||||
#define FTM0_BASE 0x40038000U
|
||||
#define FTM1_BASE 0x40039000U
|
||||
#define FTM2_BASE 0x4003A000U
|
||||
#define FTM3_BASE 0x40026000U
|
||||
#define FTM4_BASE 0x40027000U
|
||||
|
||||
#define FLEXCAN0_BASE 0x40024000U
|
||||
#define FLEXCAN1_BASE 0x40025000U
|
||||
#define FLEXCAN2_BASE 0x4002B000U
|
||||
|
||||
/* Clock Configuration */
|
||||
#define SOSC_FREQUENCY 8000000U /* System oscillator */
|
||||
#define SPLL_FREQUENCY 160000000U /* System PLL */
|
||||
#define FIRC_FREQUENCY 48000000U /* Fast IRC */
|
||||
#define SIRC_FREQUENCY 8000000U /* Slow IRC */
|
||||
|
||||
/* Peripheral Clock Configuration */
|
||||
#define FLEXCAN0_CLOCK 40000000U /* 40 MHz */
|
||||
#define FLEXCAN1_CLOCK 40000000U
|
||||
#define LPUART0_CLOCK 40000000U
|
||||
#define LPSPI0_CLOCK 40000000U
|
||||
#define LPI2C0_CLOCK 40000000U
|
||||
#define ADC0_CLOCK 40000000U
|
||||
#define FTM0_CLOCK 40000000U
|
||||
|
||||
/* NVIC Priority Configuration */
|
||||
#define FLEXCAN0_IRQ_PRIORITY 5
|
||||
#define FLEXCAN1_IRQ_PRIORITY 5
|
||||
#define LPUART0_IRQ_PRIORITY 6
|
||||
#define LPUART1_IRQ_PRIORITY 6
|
||||
#define LPSPI0_IRQ_PRIORITY 7
|
||||
#define LPI2C0_IRQ_PRIORITY 7
|
||||
#define ADC0_IRQ_PRIORITY 8
|
||||
#define FTM0_IRQ_PRIORITY 8
|
||||
|
||||
/* DMA Configuration */
|
||||
#define DMA_CHANNEL_COUNT 16
|
||||
#define DMA_MUX_CHANNEL_COUNT 16
|
||||
|
||||
/* Safety Features */
|
||||
#define ENABLE_CLOCK_MONITORING 1
|
||||
#define ENABLE_MEMORY_PROTECTION 1
|
||||
#define WATCHDOG_TIMEOUT_MS 100
|
||||
|
||||
/* Memory Configuration */
|
||||
#define FLASH_SIZE 0x100000U /* 1 MB */
|
||||
#define RAM_SIZE 0x20000U /* 128 KB */
|
||||
#define EEPROM_SIZE 0x1000U /* 4 KB */
|
||||
|
||||
/* CAN FD Configuration */
|
||||
#define CAN_FD_ENABLED 1
|
||||
#define CAN_FD_MAX_PAYLOAD 64
|
||||
|
||||
#endif /* S32K14X_CONFIG_H */
|
||||
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
* @file s32k14x_hal.c
|
||||
* @brief NXP S32K14x Hardware Abstraction Layer
|
||||
*/
|
||||
|
||||
#include "s32k14x_config.h"
|
||||
#include "can_driver.h"
|
||||
#include "uart_driver.h"
|
||||
#include "spi_driver.h"
|
||||
#include "i2c_driver.h"
|
||||
#include "gpio_driver.h"
|
||||
#include "adc_driver.h"
|
||||
#include "pwm_driver.h"
|
||||
#include "S32K144.h"
|
||||
|
||||
/* CAN HAL Implementation */
|
||||
int hal_can_init(uint32_t baudrate, uint8_t frame_type, bool enable_fd) {
|
||||
/* Enable FLEXCAN0 clock */
|
||||
PCC->PCCn[PCC_FlexCAN0_INDEX] |= PCC_PCCn_CGC_MASK;
|
||||
|
||||
/* Configure CAN pins */
|
||||
// PTE4 - CAN0_RX, PTE5 - CAN0_TX
|
||||
PCC->PCCn[PCC_PORTE_INDEX] |= PCC_PCCn_CGC_MASK;
|
||||
PORTE->PCR[4] = PORT_PCR_MUX(5); /* CAN0_RX */
|
||||
PORTE->PCR[5] = PORT_PCR_MUX(5); /* CAN0_TX */
|
||||
|
||||
/* Reset FLEXCAN */
|
||||
CAN0->MCR |= CAN_MCR_SOFTRST_MASK;
|
||||
while (CAN0->MCR & CAN_MCR_SOFTRST_MASK);
|
||||
|
||||
/* Configure for CAN FD if enabled */
|
||||
if (enable_fd) {
|
||||
CAN0->MCR |= CAN_MCR_FDEN_MASK; /* Enable FD */
|
||||
}
|
||||
|
||||
/* Set baudrate */
|
||||
uint32_t prescaler = BUS_FREQUENCY / (baudrate * 10); /* 10 time quanta */
|
||||
CAN0->CTRL1 = CAN_CTRL1_PRESDIV(prescaler - 1) |
|
||||
CAN_CTRL1_PSEG1(3) |
|
||||
CAN_CTRL1_PSEG2(2) |
|
||||
CAN_CTRL1_PROPSEG(4);
|
||||
|
||||
/* Configure message buffers */
|
||||
CAN0->RXMGMASK = 0x1FFFFFFF; /* Accept all IDs */
|
||||
CAN0->RX14MASK = 0x1FFFFFFF;
|
||||
CAN0->RX15MASK = 0x1FFFFFFF;
|
||||
|
||||
/* Enable interrupts */
|
||||
CAN0->IMASK1 |= CAN_IMASK1_BUF31TO0M_MASK;
|
||||
CAN0->MCR |= CAN_MCR_IRMQ_MASK; /* Individual RX masking */
|
||||
|
||||
/* Normal mode */
|
||||
CAN0->MCR &= ~CAN_MCR_HALT_MASK;
|
||||
while (CAN0->MCR & CAN_MCR_FRZACK_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hal_can_send_message(const CanMessage_t* message, uint32_t* mailbox) {
|
||||
/* Find free message buffer */
|
||||
*mailbox = 0;
|
||||
while (*mailbox < 32) {
|
||||
if ((CAN0->IFLAG1 & (1 << *mailbox)) != 0) {
|
||||
break;
|
||||
}
|
||||
(*mailbox)++;
|
||||
}
|
||||
|
||||
if (*mailbox >= 32) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Configure message buffer */
|
||||
CAN0->RAMn[*mailbox * 4 + 1] = (message->id.id << 18) |
|
||||
(message->id.is_extended ? 1 << 29 : 0) |
|
||||
(message->length << 16);
|
||||
|
||||
/* Copy data */
|
||||
for (int i = 0; i < message->length; i += 4) {
|
||||
uint32_t data = 0;
|
||||
for (int j = 0; j < 4 && (i + j) < message->length; j++) {
|
||||
data |= (message->data[i + j] << (j * 8));
|
||||
}
|
||||
CAN0->RAMn[*mailbox * 4 + 2 + (i / 4)] = data;
|
||||
}
|
||||
|
||||
/* Enable transmission */
|
||||
CAN0->RAMn[*mailbox * 4] = CAN_WORD0_IDE_MASK |
|
||||
CAN_WORD0_SRR_MASK |
|
||||
CAN_WORD0_ESI_MASK |
|
||||
CAN_WORD0_CODE(0xC); /* TX data */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hal_can_receive_message(CanMessage_t* message) {
|
||||
/* Check for received messages */
|
||||
uint32_t iflag = CAN0->IFLAG1;
|
||||
if (iflag == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Find received message buffer */
|
||||
uint32_t mailbox = 0;
|
||||
while (mailbox < 32) {
|
||||
if (iflag & (1 << mailbox)) {
|
||||
break;
|
||||
}
|
||||
mailbox++;
|
||||
}
|
||||
|
||||
if (mailbox >= 32) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read message */
|
||||
uint32_t word0 = CAN0->RAMn[mailbox * 4];
|
||||
uint32_t word1 = CAN0->RAMn[mailbox * 4 + 1];
|
||||
|
||||
/* Check if RX buffer */
|
||||
if ((word0 & CAN_WORD0_CODE_MASK) != CAN_WORD0_CODE(0x4)) {
|
||||
CAN0->IFLAG1 = (1 << mailbox); /* Clear flag */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get ID */
|
||||
message->id.is_extended = (word0 & CAN_WORD0_IDE_MASK) != 0;
|
||||
if (message->id.is_extended) {
|
||||
message->id.id = (word0 & CAN_WORD0_ID_MASK) >> 0;
|
||||
} else {
|
||||
message->id.id = (word0 & CAN_WORD0_ID_MASK) >> 18;
|
||||
}
|
||||
|
||||
/* Get data length */
|
||||
message->length = (word1 & CAN_WORD1_DLC_MASK) >> 16;
|
||||
|
||||
/* Get data */
|
||||
for (int i = 0; i < message->length; i += 4) {
|
||||
uint32_t data = CAN0->RAMn[mailbox * 4 + 2 + (i / 4)];
|
||||
for (int j = 0; j < 4 && (i + j) < message->length; j++) {
|
||||
message->data[i + j] = (data >> (j * 8)) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear flag */
|
||||
CAN0->IFLAG1 = (1 << mailbox);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* GPIO HAL Implementation */
|
||||
void hal_gpio_init(uint8_t port, uint8_t pin, GpioMode_t mode) {
|
||||
GPIO_Type* gpio_port = get_gpio_port(port);
|
||||
PORT_Type* port_config = get_port_config(port);
|
||||
|
||||
if (gpio_port == NULL || port_config == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable clock */
|
||||
PCC->PCCn[PCC_PORTA_INDEX + port] |= PCC_PCCn_CGC_MASK;
|
||||
PCC->PCCn[PCC_GPIOA_INDEX + port] |= PCC_PCCn_CGC_MASK;
|
||||
|
||||
/* Configure pin mux */
|
||||
switch (mode) {
|
||||
case GPIO_MODE_INPUT:
|
||||
port_config->PCR[pin] = PORT_PCR_MUX(1);
|
||||
gpio_port->PDDR &= ~(1 << pin);
|
||||
break;
|
||||
case GPIO_MODE_OUTPUT:
|
||||
port_config->PCR[pin] = PORT_PCR_MUX(1);
|
||||
gpio_port->PDDR |= (1 << pin);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void hal_gpio_write(uint8_t port, uint8_t pin, bool value) {
|
||||
GPIO_Type* gpio_port = get_gpio_port(port);
|
||||
|
||||
if (gpio_port == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
gpio_port->PSOR = (1 << pin);
|
||||
} else {
|
||||
gpio_port->PCOR = (1 << pin);
|
||||
}
|
||||
}
|
||||
|
||||
bool hal_gpio_read(uint8_t port, uint8_t pin) {
|
||||
GPIO_Type* gpio_port = get_gpio_port(port);
|
||||
|
||||
if (gpio_port == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (gpio_port->PDIR & (1 << pin)) != 0;
|
||||
}
|
||||
|
||||
/* Helper functions */
|
||||
static GPIO_Type* get_gpio_port(uint8_t port) {
|
||||
switch (port) {
|
||||
case 0: return PTA;
|
||||
case 1: return PTB;
|
||||
case 2: return PTC;
|
||||
case 3: return PTD;
|
||||
case 4: return PTE;
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PORT_Type* get_port_config(uint8_t port) {
|
||||
switch (port) {
|
||||
case 0: return PORTA;
|
||||
case 1: return PORTB;
|
||||
case 2: return PORTC;
|
||||
case 3: return PORTD;
|
||||
case 4: return PORTE;
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* @file stm32f4xx_config.h
|
||||
* @brief STM32F4 specific configuration
|
||||
*/
|
||||
|
||||
#ifndef STM32F4XX_CONFIG_H
|
||||
#define STM32F4XX_CONFIG_H
|
||||
|
||||
/* MCU Specific Definitions */
|
||||
#define STM32F407xx
|
||||
#define HSE_VALUE 8000000U /* External crystal */
|
||||
#define HSI_VALUE 16000000U /* Internal oscillator */
|
||||
#define LSE_VALUE 32768U /* Low speed external */
|
||||
#define LSI_VALUE 32000U /* Low speed internal */
|
||||
|
||||
/* Clock Configuration */
|
||||
#define SYSTEM_CLOCK 168000000U /* 168 MHz */
|
||||
#define AHB_CLOCK 168000000U
|
||||
#define APB1_CLOCK 42000000U /* 42 MHz */
|
||||
#define APB2_CLOCK 84000000U /* 84 MHz */
|
||||
|
||||
/* Peripheral Base Addresses */
|
||||
#define GPIOA_BASE 0x40020000U
|
||||
#define GPIOB_BASE 0x40020400U
|
||||
#define GPIOC_BASE 0x40020800U
|
||||
#define GPIOD_BASE 0x40020C00U
|
||||
#define GPIOE_BASE 0x40021000U
|
||||
#define GPIOF_BASE 0x40021400U
|
||||
#define GPIOG_BASE 0x40021800U
|
||||
#define GPIOH_BASE 0x40021C00U
|
||||
|
||||
#define USART1_BASE 0x40011000U
|
||||
#define USART2_BASE 0x40004400U
|
||||
#define USART3_BASE 0x40004800U
|
||||
#define UART4_BASE 0x40004C00U
|
||||
#define UART5_BASE 0x40005000U
|
||||
#define USART6_BASE 0x40011400U
|
||||
|
||||
#define SPI1_BASE 0x40013000U
|
||||
#define SPI2_BASE 0x40003800U
|
||||
#define SPI3_BASE 0x40003C00U
|
||||
|
||||
#define I2C1_BASE 0x40005400U
|
||||
#define I2C2_BASE 0x40005800U
|
||||
#define I2C3_BASE 0x40005C00U
|
||||
|
||||
#define ADC1_BASE 0x40012000U
|
||||
#define ADC2_BASE 0x40012100U
|
||||
#define ADC3_BASE 0x40012200U
|
||||
|
||||
#define TIM1_BASE 0x40010000U
|
||||
#define TIM2_BASE 0x40000000U
|
||||
#define TIM3_BASE 0x40000400U
|
||||
#define TIM4_BASE 0x40000800U
|
||||
#define TIM5_BASE 0x40000C00U
|
||||
#define TIM8_BASE 0x40010400U
|
||||
#define TIM9_BASE 0x40014000U
|
||||
#define TIM10_BASE 0x40014400U
|
||||
#define TIM11_BASE 0x40014800U
|
||||
#define TIM12_BASE 0x40001800U
|
||||
#define TIM13_BASE 0x40001C00U
|
||||
#define TIM14_BASE 0x40002000U
|
||||
|
||||
#define CAN1_BASE 0x40006400U
|
||||
#define CAN2_BASE 0x40006800U
|
||||
|
||||
/* NVIC Priority Configuration */
|
||||
#define CAN1_IRQ_PRIORITY 5
|
||||
#define CAN2_IRQ_PRIORITY 5
|
||||
#define USART1_IRQ_PRIORITY 6
|
||||
#define USART2_IRQ_PRIORITY 6
|
||||
#define USART3_IRQ_PRIORITY 6
|
||||
#define SPI1_IRQ_PRIORITY 7
|
||||
#define SPI2_IRQ_PRIORITY 7
|
||||
#define I2C1_IRQ_PRIORITY 7
|
||||
#define I2C2_IRQ_PRIORITY 7
|
||||
#define ADC_IRQ_PRIORITY 8
|
||||
#define TIM_IRQ_PRIORITY 8
|
||||
|
||||
/* DMA Configuration */
|
||||
#define DMA1_STREAM0_CHANNEL 0
|
||||
#define DMA1_STREAM1_CHANNEL 1
|
||||
#define DMA1_STREAM2_CHANNEL 2
|
||||
#define DMA1_STREAM3_CHANNEL 3
|
||||
#define DMA1_STREAM4_CHANNEL 4
|
||||
#define DMA1_STREAM5_CHANNEL 5
|
||||
#define DMA1_STREAM6_CHANNEL 6
|
||||
#define DMA1_STREAM7_CHANNEL 7
|
||||
|
||||
#define DMA2_STREAM0_CHANNEL 0
|
||||
#define DMA2_STREAM1_CHANNEL 1
|
||||
#define DMA2_STREAM2_CHANNEL 2
|
||||
#define DMA2_STREAM3_CHANNEL 3
|
||||
#define DMA2_STREAM4_CHANNEL 4
|
||||
#define DMA2_STREAM5_CHANNEL 5
|
||||
#define DMA2_STREAM6_CHANNEL 6
|
||||
#define DMA2_STREAM7_CHANNEL 7
|
||||
|
||||
/* GPIO Alternate Function Mapping */
|
||||
#define GPIO_AF_UART1_TX 7
|
||||
#define GPIO_AF_UART1_RX 7
|
||||
#define GPIO_AF_UART2_TX 7
|
||||
#define GPIO_AF_UART2_RX 7
|
||||
#define GPIO_AF_SPI1_SCK 5
|
||||
#define GPIO_AF_SPI1_MOSI 5
|
||||
#define GPIO_AF_SPI1_MISO 5
|
||||
#define GPIO_AF_I2C1_SCL 4
|
||||
#define GPIO_AF_I2C1_SDA 4
|
||||
#define GPIO_AF_CAN1_TX 9
|
||||
#define GPIO_AF_CAN1_RX 9
|
||||
#define GPIO_AF_TIM1_CH1 1
|
||||
#define GPIO_AF_TIM1_CH2 1
|
||||
#define GPIO_AF_TIM1_CH3 1
|
||||
#define GPIO_AF_TIM1_CH4 1
|
||||
|
||||
/* Memory Configuration */
|
||||
#define FLASH_SIZE 0x100000U /* 1 MB */
|
||||
#define RAM_SIZE 0x20000U /* 128 KB */
|
||||
#define CCM_RAM_SIZE 0x10000U /* 64 KB */
|
||||
|
||||
/* Safety Features */
|
||||
#define ENABLE_CLOCK_SECURITY_SYSTEM 1
|
||||
#define ENABLE_BROWN_OUT_RESET 1
|
||||
#define BROWNOUT_THRESHOLD 0x08 /* 2.7V */
|
||||
|
||||
#endif /* STM32F4XX_CONFIG_H */
|
||||
@@ -0,0 +1,289 @@
|
||||
/**
|
||||
* @file stm32f4xx_hal.c
|
||||
* @brief STM32F4 Hardware Abstraction Layer
|
||||
*/
|
||||
|
||||
#include "stm32f4xx_config.h"
|
||||
#include "can_driver.h"
|
||||
#include "uart_driver.h"
|
||||
#include "spi_driver.h"
|
||||
#include "i2c_driver.h"
|
||||
#include "gpio_driver.h"
|
||||
#include "adc_driver.h"
|
||||
#include "pwm_driver.h"
|
||||
#include "stm32f4xx.h"
|
||||
|
||||
/* CAN HAL Implementation */
|
||||
int hal_can_init(uint32_t baudrate, uint8_t frame_type, bool enable_fd) {
|
||||
/* Enable CAN clock */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
|
||||
|
||||
/* Configure CAN GPIO */
|
||||
// PB8 - CAN1_RX, PB9 - CAN1_TX
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
|
||||
|
||||
GPIOB->MODER |= (GPIO_MODER_MODER8_1 | GPIO_MODER_MODER9_1);
|
||||
GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_8 | GPIO_OTYPER_OT_9);
|
||||
GPIOB->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR8 | GPIO_OSPEEDER_OSPEEDR9);
|
||||
GPIOB->AFR[1] |= (9 << 0) | (9 << 4); /* AF9 for CAN */
|
||||
|
||||
/* Reset CAN */
|
||||
CAN1->MCR |= CAN_MCR_RESET;
|
||||
CAN1->MCR &= ~CAN_MCR_RESET;
|
||||
|
||||
/* Exit sleep mode */
|
||||
CAN1->MCR &= ~CAN_MCR_SLEEP;
|
||||
|
||||
/* Set baudrate */
|
||||
uint32_t prescaler = 0;
|
||||
uint32_t time_quantum = 0;
|
||||
|
||||
switch (baudrate) {
|
||||
case 125000:
|
||||
prescaler = 21;
|
||||
time_quantum = 16;
|
||||
break;
|
||||
case 250000:
|
||||
prescaler = 11;
|
||||
time_quantum = 15;
|
||||
break;
|
||||
case 500000:
|
||||
prescaler = 5;
|
||||
time_quantum = 16;
|
||||
break;
|
||||
case 1000000:
|
||||
prescaler = 3;
|
||||
time_quantum = 14;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
CAN1->BTR = ((prescaler - 1) << 20) |
|
||||
((time_quantum - 1) << 16) |
|
||||
(3 << 20) | /* SJW = 4 */
|
||||
(7 << 16); /* BS1 = 8 */
|
||||
|
||||
/* Configure filters */
|
||||
CAN1->FMR |= CAN_FMR_FINIT;
|
||||
CAN1->FM1R &= ~CAN_FM1R_FBM0; /* Mask mode for filter 0 */
|
||||
CAN1->FS1R |= CAN_FS1R_FSC0; /* 32-bit scale */
|
||||
CAN1->FFA1R &= ~CAN_FFA1R_FFA0; /* FIFO 0 */
|
||||
CAN1->FMR &= ~CAN_FMR_FINIT;
|
||||
|
||||
/* Enable interrupts */
|
||||
CAN1->IER |= CAN_IER_FMPIE0 | /* FIFO 0 message pending */
|
||||
CAN_IER_TMEIE | /* Transmit mailbox empty */
|
||||
CAN_IER_BOFIE | /* Bus-off */
|
||||
CAN_IER_ERRIE; /* Error */
|
||||
|
||||
/* Normal mode */
|
||||
CAN1->MCR &= ~CAN_MCR_SLEEP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hal_can_send_message(const CanMessage_t* message, uint32_t* mailbox) {
|
||||
/* Check for free mailbox */
|
||||
if ((CAN1->TSR & CAN_TSR_TME0) != 0) {
|
||||
*mailbox = 0;
|
||||
} else if ((CAN1->TSR & CAN_TSR_TME1) != 0) {
|
||||
*mailbox = 1;
|
||||
} else if ((CAN1->TSR & CAN_TSR_TME2) != 0) {
|
||||
*mailbox = 2;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Configure mailbox */
|
||||
CAN_TxMailBox_TypeDef* tx_mailbox = &CAN1->sTxMailBox[*mailbox];
|
||||
|
||||
/* Set ID */
|
||||
if (message->id.is_extended) {
|
||||
tx_mailbox->TIR = (message->id.id << 3) | CAN_TI0R_IDE;
|
||||
} else {
|
||||
tx_mailbox->TIR = (message->id.id << 21);
|
||||
}
|
||||
|
||||
/* Set data length and data */
|
||||
tx_mailbox->TDTR = message->length;
|
||||
|
||||
/* Copy data */
|
||||
uint32_t data[2] = {0, 0};
|
||||
for (int i = 0; i < message->length; i++) {
|
||||
if (i < 4) {
|
||||
data[0] |= (message->data[i] << (i * 8));
|
||||
} else {
|
||||
data[1] |= (message->data[i] << ((i - 4) * 8));
|
||||
}
|
||||
}
|
||||
|
||||
tx_mailbox->TDLR = data[0];
|
||||
tx_mailbox->TDHR = data[1];
|
||||
|
||||
/* Request transmission */
|
||||
tx_mailbox->TIR |= CAN_TI0R_TXRQ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hal_can_receive_message(CanMessage_t* message) {
|
||||
/* Check if message available */
|
||||
if ((CAN1->RF0R & CAN_RF0R_FMP0) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get message */
|
||||
CAN_FIFOMailBox_TypeDef* rx_mailbox = &CAN1->sFIFOMailBox[0];
|
||||
|
||||
/* Get ID */
|
||||
if (rx_mailbox->RIR & CAN_RI0R_IDE) {
|
||||
message->id.is_extended = true;
|
||||
message->id.id = (rx_mailbox->RIR >> 3) & 0x1FFFFFFF;
|
||||
} else {
|
||||
message->id.is_extended = false;
|
||||
message->id.id = (rx_mailbox->RIR >> 21) & 0x7FF;
|
||||
}
|
||||
|
||||
/* Get data length */
|
||||
message->length = rx_mailbox->RDTR & CAN_RDT0R_DLC;
|
||||
|
||||
/* Get data */
|
||||
uint32_t data_low = rx_mailbox->RDLR;
|
||||
uint32_t data_high = rx_mailbox->RDHR;
|
||||
|
||||
for (int i = 0; i < message->length; i++) {
|
||||
if (i < 4) {
|
||||
message->data[i] = (data_low >> (i * 8)) & 0xFF;
|
||||
} else {
|
||||
message->data[i] = (data_high >> ((i - 4) * 8)) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release FIFO */
|
||||
CAN1->RF0R |= CAN_RF0R_RFOM0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* GPIO HAL Implementation */
|
||||
void hal_gpio_init(uint8_t port, uint8_t pin, GpioMode_t mode) {
|
||||
GPIO_TypeDef* gpio_port = get_gpio_port(port);
|
||||
|
||||
if (gpio_port == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable GPIO clock */
|
||||
RCC->AHB1ENR |= (1 << port);
|
||||
|
||||
/* Configure mode */
|
||||
uint32_t moder_value = 0;
|
||||
switch (mode) {
|
||||
case GPIO_MODE_INPUT:
|
||||
moder_value = 0x00;
|
||||
break;
|
||||
case GPIO_MODE_OUTPUT:
|
||||
moder_value = 0x01;
|
||||
break;
|
||||
case GPIO_MODE_ALTERNATE:
|
||||
moder_value = 0x02;
|
||||
break;
|
||||
case GPIO_MODE_ANALOG:
|
||||
moder_value = 0x03;
|
||||
break;
|
||||
}
|
||||
|
||||
gpio_port->MODER &= ~(0x03 << (pin * 2));
|
||||
gpio_port->MODER |= (moder_value << (pin * 2));
|
||||
}
|
||||
|
||||
void hal_gpio_write(uint8_t port, uint8_t pin, bool value) {
|
||||
GPIO_TypeDef* gpio_port = get_gpio_port(port);
|
||||
|
||||
if (gpio_port == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
gpio_port->BSRR = (1 << pin);
|
||||
} else {
|
||||
gpio_port->BSRR = (1 << (pin + 16));
|
||||
}
|
||||
}
|
||||
|
||||
bool hal_gpio_read(uint8_t port, uint8_t pin) {
|
||||
GPIO_TypeDef* gpio_port = get_gpio_port(port);
|
||||
|
||||
if (gpio_port == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (gpio_port->IDR & (1 << pin)) != 0;
|
||||
}
|
||||
|
||||
/* UART HAL Implementation */
|
||||
int hal_uart_init(uint8_t instance, UartConfig_t* config) {
|
||||
USART_TypeDef* uart = get_uart_instance(instance);
|
||||
|
||||
if (uart == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Enable clock */
|
||||
if (instance == 0) {
|
||||
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
|
||||
} else {
|
||||
RCC->APB1ENR |= (RCC_APB1ENR_USART2EN << (instance - 1));
|
||||
}
|
||||
|
||||
/* Configure baudrate */
|
||||
uint32_t clock = (instance == 0 || instance == 5) ? APB2_CLOCK : APB1_CLOCK;
|
||||
uart->BRR = clock / config->baudrate;
|
||||
|
||||
/* Configure control registers */
|
||||
uart->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
|
||||
|
||||
if (config->data_bits == UART_DATA_BITS_9) {
|
||||
uart->CR1 |= USART_CR1_M;
|
||||
}
|
||||
|
||||
uart->CR2 = 0;
|
||||
if (config->stop_bits == UART_STOP_BITS_2) {
|
||||
uart->CR2 |= USART_CR2_STOP_1;
|
||||
}
|
||||
|
||||
/* Enable interrupts */
|
||||
if (config->enable_rx) {
|
||||
uart->CR1 |= USART_CR1_RXNEIE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Helper functions */
|
||||
static GPIO_TypeDef* get_gpio_port(uint8_t port) {
|
||||
switch (port) {
|
||||
case 0: return GPIOA;
|
||||
case 1: return GPIOB;
|
||||
case 2: return GPIOC;
|
||||
case 3: return GPIOD;
|
||||
case 4: return GPIOE;
|
||||
case 5: return GPIOF;
|
||||
case 6: return GPIOG;
|
||||
case 7: return GPIOH;
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static USART_TypeDef* get_uart_instance(uint8_t instance) {
|
||||
switch (instance) {
|
||||
case 0: return USART1;
|
||||
case 1: return USART2;
|
||||
case 2: return USART3;
|
||||
case 3: return UART4;
|
||||
case 4: return UART5;
|
||||
case 5: return USART6;
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user