QSPI DMA UART
QSPI DMA UART示例实现了采用QSPI接口连接外部Falsh,读取Flash中的数据并通过UART DMA方式传输数据。
QSPI DMA UART示例的源代码和工程文件位于SDK_Folder\projects\peripheral\qspi\qspi_flash_dma_uart,其中工程文件在文件夹Keil_5下。
代码理解
示例工程流程图如图 38所示:
- 配置QSPI DMA UART。
g_qspi_handle.init.clock_prescaler = SystemCoreClock / 1000000; g_qspi_handle.init.clock_mode = QSPI_CLOCK_MODE_3; g_qspi_handle.init.rx_sample_delay = 0; hal_qspi_deinit(&g_qspi_handle); if (HAL_OK != hal_qspi_init(&g_qspi_handle)) { printf("\r\nFlash initial failed.\r\n"); return 0; } uart_handle.p_instance = UART1; uart_handle.init.baud_rate = 115200; uart_handle.init.data_bits = UART_DATABITS_8; uart_handle.init.stop_bits = UART_STOPBITS_1; uart_handle.init.parity = UART_PARITY_NONE; uart_handle.init.hw_flow_ctrl = UART_HWCONTROL_NONE; uart_handle.init.rx_timeout_mode = UART_RECEIVER_TIMEOUT_DISABLE; hal_uart_deinit(&uart_handle); hal_uart_init(&uart_handle);- 配置QSPI模块。
配置QSPI的时钟为1 MHz,配置空闲状态时的时钟信号为高电平。
- 配置UART模块。
UART详细配置信息请参考UART DMA。其中UART配置为UART1。
- 配置QSPI模块。
- 调用hal_qspi_init()初始化QSPI模块。代码如下:
hal_qspi_init(&g_qspi_handle) - 调用SPI_FLASH_Read_Device_ID()获取Flash的设备ID。代码如下:
device_id = SPI_FLASH_Read_Device_ID(); printf("Read_Device_ID = 0x%06X\r\n", device_id); - 调用SPI_FLASH_Read()读取Flash中的数据。代码如下:
SPI_FLASH_Read(FLASH_PROGRAM_START_ADDR, flash_buffer, FLASH_PAGE_SIZE); for (i = 0; i < FLASH_PAGE_SIZE; i++) { if (flash_buffer[i] != 0xFF) break; } if (i < FLASH_PAGE_SIZE) { printf("Erase Sector...\r\n"); SPI_FLASH_Sector_Erase(FLASH_PROGRAM_START_ADDR); printf("Erase Sector Success.\r\n"); } - 调用SPI_FLASH_Page_Program()向Flash写数据。代码如下:
printf("Page_Program...\r\n"); SPI_FLASH_Page_Program(FLASH_PROGRAM_START_ADDR, flash_buffer); printf("Page Program Success.\r\n"); - 配置QSPI模式为QSPI模式,配置数据位宽为32位,传输目的为EEPROM,输出大小为(FLASH_PAGE_SIZE >> 2) - 1。代码如下:
/* Config QSPI in SPI mode, data size is 32bits */ __HAL_QSPI_DISABLE(p_qspi_handle); ll_spi_set_frame_format(p_qspi_handle->p_instance, LL_SSI_FRF_SPI); ll_spi_set_data_size(p_qspi_handle->p_instance, LL_SSI_DATASIZE_8BIT); ll_spi_set_transfer_direction(p_qspi_handle->p_instance, LL_SSI_READ_EEPROM); ll_spi_set_receive_size(p_qspi_handle->p_instance, FLASH_PAGE_SIZE - 1); __HAL_QSPI_ENABLE(p_qspi_handle); - 配置UART1 FIFO threshold 和burst length。代码如下:
/* Config FIFO threshold of UART and burst length of DMA */ ll_uart_set_tx_fifo_threshold(uart_handle.p_instance, LL_UART_TX_FIFO_TH_QUARTER_FULL); ll_uart_enable_it(uart_handle.p_instance, UART_IT_THRE); ll_dma_set_source_burst_length(DMA, p_qspi_handle->p_dma->channel, LL_DMA_SRC_BURST_LENGTH_1); ll_dma_set_destination_burst_length(DMA, p_qspi_handle->p_dma->channel, LL_DMA_DST_BURST_LENGTH_8); - 开始DMA传输并等待传输完成。代码如下:
uint32_t cmd_addr = ((uint32_t)SPI_FLASH_CMD_READ << 24) | FLASH_PROGRAM_START_ADDR; hal_dma_start(p_qspi_handle->p_dma, (uint32_t)& p_qspi_handle->p_instance->DATA, (uint32_t)&UART1->RBR_DLL_THR, FLASH_PAGE_SIZE); p_qspi_handle->p_instance->DATA = (cmd_addr >> 24 ) & 0xff; p_qspi_handle->p_instance->DATA = (cmd_addr >> 16 ) & 0xff; p_qspi_handle->p_instance->DATA = (cmd_addr >> 8 ) & 0xff; p_qspi_handle->p_instance->DATA = (cmd_addr >> 0 ) & 0xff; __HAL_QSPI_ENABLE_DMARX(p_qspi_handle); ll_spi_enable_ss(p_qspi_handle->p_instance, LL_SSI_SLAVE0); hal_status_t status = hal_dma_poll_for_transfer(p_qspi_handle->p_dma, 1000); if (status == HAL_OK) { printf("Transfer finished.\r\n"); } else { printf("Transfer failed, hal_status = %d\r\n", status); }
测试验证
- 用GProgrammer下载qspi_flash_dma_uart.bin至开发板。
- 将开发板串口连接至PC端,打开并配置GRUart。
- 在GRUart的Receive Data窗口中将会显示QSPI FLASH UART的交互数据信息。