Files
CCU621M/BSP/sys_drv_init.c
T

186 lines
6.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "sys_drv_init.h"
#include "gpio.h"
#include "usart.h"
#include "app_rtc/app_rtc.h"
#include "gd32h7xx.h"
#include "can.h"
#include "adc_temp.h"
#include "nandflash_exmc_MT29F4G08.h"
#include "exflash_spi4_gd25qxx.h"
#include "flash_external_data.h"
#include "adc_spi3_insuVolt.h"
#include "adc_spi5_batVoltCurr.h"
#include "fm24cl16.h"
#include "tim/app_tim.h"
#include "main.h"
//#include <cachel1_armv7.h>
/**
* @brief 使能 Cortex-M7 指令/数据缓存
* @note 先失效 D-Cache,再开启 D-Cache,避免历史脏数据影响
*/
static void cache_enable(void)
{
SCB_EnableICache();
SCB_DisableDCache();
SCB_InvalidateDCache();
SCB_EnableDCache();
}
/**
* @brief 配置 NVIC 优先级分组
* @note FreeRTOS 建议使用 PRE4_SUB0(4 位抢占优先级 + 0 位子优先级)
*/
static void nvic_configuration(void)
{
/* 统一中断优先级配置入口(参考 CCU601E_D 的 NVIC_Priority_Config 思路) */
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
/* ENET IRQ 内会调用 xSemaphoreGiveFromISR,优先级必须 >= configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY(5) */
#ifdef USE_ENET0
nvic_irq_enable(ENET0_IRQn, 6U, 0U);
#endif
#ifdef USE_ENET1
nvic_irq_enable(ENET1_IRQn, 6U, 0U);
#endif
/* USART/UART 中断优先级统一配置 */
nvic_irq_enable(USART0_IRQn, 3U, 1U);
nvic_irq_enable(USART2_IRQn, 3U, 2U);
nvic_irq_enable(UART3_IRQn, 3U, 0U);
nvic_irq_enable(UART4_IRQn, 2U, 0U);
nvic_irq_enable(USART5_IRQn, 1U, 0U);
nvic_irq_enable(UART6_IRQn, 0U, 0U);
nvic_irq_enable(UART7_IRQn, 3U, 7U);
/* ADC DMA 中断优先级统一配置 */
nvic_irq_enable(DMA1_Channel0_IRQn, 6U, 0U);
/* CAN 中断优先级统一配置 */
nvic_irq_enable(CAN0_Message_IRQn, 0U, 0U);
nvic_irq_enable(CAN1_Message_IRQn, 0U, 0U);
nvic_irq_enable(CAN2_Message_IRQn, 0U, 0U);
/* CAN error/busoff/warning IRQs (some CAN configs may route events here) */
nvic_irq_enable(CAN0_Busoff_IRQn, 0U, 0U);
nvic_irq_enable(CAN0_Error_IRQn, 0U, 0U);
nvic_irq_enable(CAN0_TEC_IRQn, 0U, 0U);
nvic_irq_enable(CAN0_REC_IRQn, 0U, 0U);
nvic_irq_enable(CAN1_Busoff_IRQn, 0U, 0U);
nvic_irq_enable(CAN1_Error_IRQn, 0U, 0U);
nvic_irq_enable(CAN1_TEC_IRQn, 0U, 0U);
nvic_irq_enable(CAN1_REC_IRQn, 0U, 0U);
nvic_irq_enable(CAN2_Busoff_IRQn, 0U, 0U);
nvic_irq_enable(CAN2_Error_IRQn, 0U, 0U);
nvic_irq_enable(CAN2_TEC_IRQn, 0U, 0U);
nvic_irq_enable(CAN2_REC_IRQn, 0U, 0U);
nvic_irq_enable(TIMER7_UP_IRQn, 5U, 0U);
}
/**
* @brief 配置 MPUMemory Protection Unit)区域属性
*
* 详细说明:
* 1) 该函数主要用于给“被 DMA 与 CPU 同时访问”的内存区域设置合适的属性,
* 避免 D-Cache 引入的数据一致性问题(CPU 看到旧数据、DMA 写入不可见等)。
*
* 2) 当前配置了两块 16KB 区域(均位于 SRAM3):
* - 区域00x30000000 ~ 0x30003FFF
* 典型用于 DMA 描述符、ETH Rx/Tx 缓冲等需要强一致性的内存。
* - 区域10x30004000 ~ 0x30007FFF
* 典型用于 lwIP heappbuf/memp 等运行期内存)。
*
* 3) 两个区域都设置为 Non-Cacheable(不可缓存):
* - 目的:让 CPU 每次都从实际内存读取,保证与 DMA 读写一致。
* - 代价:这部分区域访问速度会比 Cacheable 区域慢,但稳定性更高。
*
* 4) 该函数应在外设初始化前执行(当前在 v_sys_hardware_init() 早期调用),
* 这样后续网络/DMA模块在运行时就使用了正确的内存属性。
*
* 5) 结论:此函数是“网络与 DMA 稳定运行”的基础配置,尤其在 Cortex-M7
* 启用 D-Cache 场景下必不可少。
*/
void mpu_config(void)
{
mpu_region_init_struct mpu_init_struct;
mpu_region_struct_para_init(&mpu_init_struct);
/* disable MPU */
ARM_MPU_SetRegion(0U, 0U);
/* 区域0:DMA描述符/收发缓冲区(非缓存,避免 DMA 与 Cache 不一致) */
mpu_init_struct.region_base_address = 0x30000000;
mpu_init_struct.region_size = MPU_REGION_SIZE_16KB;
mpu_init_struct.access_permission = MPU_AP_FULL_ACCESS;
mpu_init_struct.access_bufferable = MPU_ACCESS_BUFFERABLE;
mpu_init_struct.access_cacheable = MPU_ACCESS_NON_CACHEABLE;
mpu_init_struct.access_shareable = MPU_ACCESS_NON_SHAREABLE;
mpu_init_struct.region_number = MPU_REGION_NUMBER0;
mpu_init_struct.subregion_disable = MPU_SUBREGION_ENABLE;
mpu_init_struct.instruction_exec = MPU_INSTRUCTION_EXEC_PERMIT;
mpu_init_struct.tex_type = MPU_TEX_TYPE0;
mpu_region_config(&mpu_init_struct);
mpu_region_enable();
/* 区域1lwIP heap(非缓存 + shareable,便于总线主设备协同访问) */
mpu_init_struct.region_base_address = 0x30004000;
mpu_init_struct.region_size = MPU_REGION_SIZE_16KB;
mpu_init_struct.access_permission = MPU_AP_FULL_ACCESS;
mpu_init_struct.access_bufferable = MPU_ACCESS_NON_BUFFERABLE;
mpu_init_struct.access_cacheable = MPU_ACCESS_NON_CACHEABLE;
mpu_init_struct.access_shareable = MPU_ACCESS_SHAREABLE;
mpu_init_struct.region_number = MPU_REGION_NUMBER1;
mpu_init_struct.subregion_disable = MPU_SUBREGION_ENABLE;
mpu_init_struct.instruction_exec = MPU_INSTRUCTION_EXEC_PERMIT;
mpu_init_struct.tex_type = MPU_TEX_TYPE1;
mpu_region_config(&mpu_init_struct);
mpu_region_enable();
/* enable MPU */
ARM_MPU_Enable(MPU_MODE_PRIV_DEFAULT);
}
/**
* @brief 系统硬件初始化总入口
* @note 按“基础系统 -> 通信/IO -> 业务外设”顺序初始化
*/
void v_sys_hardware_init(void)
{
/* 基础系统配置 */
nvic_configuration();
mpu_config();
cache_enable();
/* 基础外设 */
/* 先初始化关键DO输出,避免上电过程继电器抖动/误动作 */
v_outpin_config();
v_rtc_init();
v_inpin_config();
/* 通信外设 */
v_usart_init_all();
/* EEPROM(FM24CL16) I2C1 初始化 */
eeprom_driver_init();
/* SPI Flash 驱动初始化(统一封装接口) */
(void)v_flash_dataflash_init();
/* CAN init moved into hardware stage to avoid first-frame loss after power-on. */
v_can_interface_init();
/* 1ms hardware timer interrupt for periodic software counters. */
v_app_tim_init();
/* 以太网与 lwIP 须在 FreeRTOS 调度器启动后初始化(见 app_os_init),
* 否则 enet_system_setup() 失败会死在 while(1),运行灯也不会亮。 */
/* 采样与电源相关外设 */
adc_spi3_insuVolt_init();
adc_spi5_batVoltCurr_init();
v_temp_config();
// v_4g_config();
/* 可选外设(按需启用)
exmc_nandflash_init();
lwip_system_init();
*/
}