修改点如下:
一,进入standby保证uart通
1, 去掉串口进入休眠RT_DEVICE_CTRL_SUSPEND:关闭uart,保证BSP_IO_Power_Down函数执行完前,串口都可以打印,和通过SifliUsartServer工具串口连接,并debug死机问题;

二,从standby唤醒保证uart通
standby唤醒打开串口比较麻烦,此时RTT系统还没有恢复,外部Nor/Nand Flash都没有初始化不可以用,除了Retention RAM外,其他的RAM也还不能访问,打通Uart的思路,就是在GPIO通了HAL_HPAON_ENABLE_PAD();以后,对uart进行初始化配置,并且此时的代码都需要放在RAM内运行,rt_kprintf(""); 在rtt系统和恢复RT_DEVICE_CTRL_RESUME:之前,都是不能打印的,如果一定要打印,用hal_printf("BSP_Power_Up\n");打印,而且不能在if (PM_STANDBY_BOOT == SystemPowerOnModeGet()) 待机唤醒起来的代码内才能运行,其他上电时uart没有初始化,也是会死机;修改点如下:
-
drv_usart.c文件新增加的hal初始uart的函数和打印函数;
/* UART handler declaration */ static UART_HandleTypeDef UartHandle; #define BUFFER_SIZE 256 #define HALF_BUFFER_SIZE (BUFFER_SIZE/2) static DMA_HandleTypeDef dma_rx_handle; static uint8_t buffer[BUFFER_SIZE]; // 定义接收状态枚举 typedef enum { STATE_UNFULL, STATE_HALF_FULL, STATE_FULL } ReceiveState; // 当前接收状态 ReceiveState currentState = STATE_UNFULL; HAL_RAM_RET_CODE_SECT(HAL_UART_CONFIG, static void HAL_UART_CONFIG(struct sifli_uart_config *cfg, rt_size_t obj_num, rt_uint32_t baud_rate)) { /* Output a message on console using printf function */ for (int i = 0; i < obj_num; i++) { /*##-1- Configure the UART peripheral ######################################*/ /* Put the USART peripheral in the Asynchronous mode (UART Mode) */ /* UART configured as follows: - Word Length = 8 Bits (8 data bit + 0 parity bit) : BE CAREFUL : Program 7 data bits + 1 parity bit in PC HyperTerminal - Stop Bit = One Stop bit - Parity = No parity - BaudRate = 1000000 baud - Hardware flow control disabled (RTS and CTS signals) */ UartHandle.Instance = cfg->Instance; UartHandle.Init.BaudRate = RT_SERIAL_DEFAULT_BAUDRATE; UartHandle.Init.WordLength = UART_WORDLENGTH_8B; UartHandle.Init.StopBits = UART_STOPBITS_1; UartHandle.Init.Parity = UART_PARITY_NONE; UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; UartHandle.Init.Mode = UART_MODE_TX_RX; UartHandle.Init.OverSampling = UART_OVERSAMPLING_16; if (UartHandle.Init.Parity) { // If parity is odd/even, parity should +1 UartHandle.Init.WordLength = UART_WORDLENGTH_9B; } /* 1, pinmux set to uart mode */ HAL_PIN_Set(PAD_PA30, USART1_RXD, PIN_PULLUP, 1); // UART1_RXD HAL_PIN_Set(PAD_PA34, USART1_TXD, PIN_PULLUP, 1); // UART1_TXD /* 2, open uart2 clock source */ HAL_RCC_EnableModule(RCC_MOD_USART1); if (HAL_UART_Init(&UartHandle) != HAL_OK) { /* Initialization Error */ HAL_ASSERT(0); } // Start RX DMA __HAL_LINKDMA(&(UartHandle), hdmarx, dma_rx_handle); dma_rx_handle.Instance = cfg->dma_rx->Instance; dma_rx_handle.Init.Request = cfg->dma_rx->request; HAL_UART_DmaTransmit(&UartHandle, buffer, BUFFER_SIZE, DMA_PERIPH_TO_MEMORY); /* DMA_PERIPH_TO_MEMORY */ #ifndef DMA_SUPPORT_DYN_CHANNEL_ALLOC // Enable DMA IRQ HAL_NVIC_SetPriority(cfg->dma_rx->dma_irq_prio, 0, 0); HAL_NVIC_EnableIRQ(cfg->dma_rx->dma_irq); #endif /* !DMA_SUPPORT_DYN_CHANNEL_ALLOC */ { // For RX DMA, also need to enable UART IRQ. __HAL_UART_ENABLE_IT(&UartHandle, UART_IT_IDLE); /* Set to generates interrupts when UART idle */ HAL_NVIC_SetPriority(cfg->dma_rx->dma_irq_prio, 1, 0); HAL_NVIC_EnableIRQ(cfg->dma_rx->dma_irq); } /* Output a message on Hyperterminal using printf function */ /* Output a message on Hyperterminal using hal function */ uint8_t ptr[] = {'u', 'a', 'r', 't', '1', ' ', 'r', 'e', 'a', 'd', 'y', '\n'}; int len = sizeof(ptr); HAL_UART_Transmit(&UartHandle, ptr, len, 0xFFFF); } } HAL_RAM_RET_CODE_SECT(hal_hw_usart_init, void hal_hw_usart_init(void)) { rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct sifli_uart); if (obj_num > 0) { sifli_uart_get_dma_config(); HAL_UART_CONFIG(uart_config, obj_num, RT_SERIAL_DEFAULT_BAUDRATE); } } HAL_RAM_RET_CODE_SECT(hal_printf, void hal_printf(char *fmt, ...)) { HAL_UART_Transmit(&UartHandle, fmt, 20, 0xFFFF); }

2,相关hal初始uart的函数和打印函数以及调用的底层HAL文件都要放到RAM内运行,

就是这三个文件,HAL_RAM_RET_CODE_SECT(hal_hw_usart_init, void hal_hw_usart_init(void))这个函数都要调用到,需要放到RAM内,要添加在RW_IRAM_RET HPSYS_RETM_BASE HPSYS_RETM_SIZE {这个段内,如下图:

其中HAL_RAM_RET_CODE_SECT 已经对hal_hw_usart_init 函数单独声明了放在RAM内;
- 检查相关文件是否已经放到了RAM内,搜索生成*.map文件:
对于的函数地址在 retention RAM区间,就是对了,

确认一下hal_hw_usart_init函数存放地址,如果是在0x20000000到0x2001FFFF内,就是对的,如果地址在0x1C00xxxx开头的,就还是在flash上运行,会死机的;

确认一下,这个函数:HAL_NVIC_SetPriority的存放地址:

- 如果你的工程目录下,没有sf32lb56x的话,就这个目录的link.lds和link.sct复制过去也是可以的,
还有一种加法,就是在56x默认的link文件里面加,编译规则是如果有sf32lb56x的link文件,就不用下面这个目录的了。

- 就是在hcpu唤醒的函数内,添加新增加的uart的初始化函数,56的hcpu在唤醒走的第一个函数就是:SystemInitFromStandby,
在这个函数内添加 调用,
extern int hal_hw_usart_init();
hal_hw_usart_init();
5,通过上面操作后,Hcpu在死机时,Uart就能通了,并且可以通过SifliUsartServer工具串口连接,并debug死机问题了
