这里会显示出您选择的修订版和当前版本之间的差别。
后一修订版 | 前一修订版 | ||
icore4trtt_14 [2020/11/18 11:09] zgf 创建 |
icore4trtt_14 [2022/04/01 11:11] (当前版本) sean |
||
---|---|---|---|
行 2: | 行 2: | ||
|技术支持电话|**0379-69926675-801**||| | |技术支持电话|**0379-69926675-801**||| | ||
|技术支持邮件|Gingko@vip.163.com||| | |技术支持邮件|Gingko@vip.163.com||| | ||
- | |技术论坛|http://www.eeschool.org||| | ||
^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | ||
| V1.0 | 2020-11-18 | zh. | 初次建立 | | | V1.0 | 2020-11-18 | zh. | 初次建立 | | ||
- | ===== iCore4T_RTT_5_添加QSPI设备驱动 ===== | + | ===== iCore4T_RTT_14_添加SPI驱动,读写FPGA ===== |
- | * iCore4T核心板通过QSPI总线挂有一片 8MB FLASH W25Q64可用于运行程序、存放字库、存放图片、做为文件系统的从设备等,那么我们怎么把它用起来呢,今天给大家分享一下QSPI总线驱动的加载过程及W25Q64的挂载过程。 | + | iCore4T上,RAM通过SPI4总线与FPGA通信,今天,我将给大家分享RTT添加SPI总线和FPGA驱动,最后实现FPGA的读写测试。 |
- | ==== 一、配置QSPI相应的GPIO,选择QSPI的时钟源 ==== | + | ==== 1、修改board文件夹下kconfig文件,在menu "Onboard Peripheral Drivers"中添加配置FPGA选项,在menu "On-chip Peripheral Drivers"配置SPI总线并在menuconfig菜单配置中勾选。 ==== |
+ | {{ :icore4t:iCore4T_RTT_14_1.png?direct |}} | ||
+ | {{ :icore4t:iCore4T_RTT_14_2.png?direct |}} | ||
+ | {{ :icore4t:iCore4T_RTT_14_3.png?direct |}} | ||
+ | {{ :icore4t:iCore4T_RTT_14_4.png?direct |}} | ||
- | * 1.1 我们仍然是借助STM32CubeMx工具来完成外设IO的配置,打开../bsp/stm32/stm32h750-gingko-icore4t/board/CubeMX_Config来配置QSPI的IO,从原理图中可以看到我们用的是QSPI的BANK1,它的IO分别是PB2(CLK)、PB6(NCS)、PD11(IO0)、PD12(IO1)、PD13(IO3)、PF7(IO2)。打开QSPI后,默认给出的IO和我们原理图中的并不相符,这里我们手动修改一下,仍然是只配置IO,选择QSPI的时钟源。配置完成点击CREATE CODE。 | + | ==== 2、在文件路径stm32\libraries\HAL_Drivers下,我们修改SConscript文件,将drv_spi_fpga.c源文件添加到编译脚本中去。 ==== |
- | {{ :icore4t:iCore4T_RTT_5_1.png?direct |}} | + | |
+ | {{ :icore4t:iCore4T_RTT_14_5.png?direct |}} | ||
+ | |||
+ | |||
+ | ==== 3、drv_spi_fpga.c文件内容贴在下面。 ==== | ||
+ | <code> | ||
+ | /* | ||
+ | * Copyright (c) 2006-2018, RT-Thread Development Team | ||
+ | * | ||
+ | * SPDX-License-Identifier: Apache-2.0 | ||
+ | * | ||
+ | * Change Logs: | ||
+ | * Date Author Notes | ||
+ | * 2020-02-17 zh. first version | ||
+ | */ | ||
+ | |||
+ | #include <board.h> | ||
+ | #include <drv_spi.h> | ||
+ | #include <rtdevice.h> | ||
+ | #include <rthw.h> | ||
+ | #include <finsh.h> | ||
+ | |||
+ | #include <ctype.h> | ||
+ | #include <string.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | #ifdef BSP_USING_SPI_FPGA | ||
+ | |||
+ | /* fpga command */ | ||
+ | #define FPGA_READ_ID_CMD 0x01 | ||
+ | #define FPGA_WRITE_LEN_CMD 0x02 | ||
+ | #define FPGA_WRITE_STATE_CMD 0x03 | ||
+ | #define FPGA_WRITE_CMD 0x04 | ||
+ | #define FPGA_READ_LEN_CMD 0x05 | ||
+ | #define FPGA_READ_STATE_CMD 0x06 | ||
+ | #define FPGA_READ_CMD 0x07 | ||
+ | |||
+ | /* spi bus device name*/ | ||
+ | #define FPGA_SPI_DEVICE_NAME "spi4" | ||
+ | |||
+ | /* spi device name*/ | ||
+ | #define FPGA_DEVICE_NAME "FPGA" | ||
+ | |||
+ | struct rt_spi_device *spi4_device; | ||
+ | |||
+ | |||
+ | static int spi_write_read_test(void) | ||
+ | { | ||
+ | rt_uint32_t i; | ||
+ | rt_uint32_t temp; | ||
+ | rt_size_t t_size = 0; | ||
+ | rt_uint8_t send_buffer[1028]; | ||
+ | rt_uint8_t recv_buffer[1028]; | ||
+ | rt_uint8_t error = 0; | ||
+ | float speed; | ||
+ | |||
+ | /* write command */ | ||
+ | send_buffer[0] = FPGA_WRITE_CMD; | ||
+ | send_buffer[1] = 0x00; | ||
+ | send_buffer[2] = 0x00; | ||
+ | /* pseudo command */ | ||
+ | send_buffer[1027] = 0x00; | ||
+ | |||
+ | for(i = 0;i < 1024;i ++) | ||
+ | { | ||
+ | send_buffer[i + 3] = i % 256; | ||
+ | } | ||
+ | |||
+ | // t_size = rt_spi_transfer(spi4_device,send_buffer,recv_buffer,sizeof(send_buffer)); | ||
+ | temp = HAL_GetTick(); | ||
+ | for(i = 0;i < 10240;i ++) | ||
+ | { | ||
+ | t_size = rt_spi_transfer(spi4_device,send_buffer,recv_buffer,sizeof(send_buffer)); | ||
+ | } | ||
+ | temp = HAL_GetTick() - temp; | ||
+ | |||
+ | if(t_size != sizeof(send_buffer)) | ||
+ | { | ||
+ | rt_kprintf("fpga write fail!\n"); | ||
+ | return RT_ERROR; | ||
+ | } | ||
+ | |||
+ | rt_thread_mdelay(100); | ||
+ | |||
+ | //read_command | ||
+ | send_buffer[0] = FPGA_READ_CMD; | ||
+ | send_buffer[1] = 0x00; | ||
+ | send_buffer[2] = 0x00; | ||
+ | /* pseudo command */ | ||
+ | send_buffer[3] = 0x00; | ||
+ | |||
+ | |||
+ | memset(recv_buffer,0,sizeof(recv_buffer)); | ||
+ | |||
+ | t_size = rt_spi_transfer(spi4_device,send_buffer,recv_buffer,sizeof(send_buffer)); | ||
+ | |||
+ | if(t_size != sizeof(send_buffer)) | ||
+ | { | ||
+ | rt_kprintf("fpga read fail!\n"); | ||
+ | return RT_ERROR; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | for(i = 0;i < 1024;i ++) | ||
+ | { | ||
+ | if(recv_buffer[i+4] != i%256) | ||
+ | { | ||
+ | error ++; | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | if(error) | ||
+ | { | ||
+ | rt_kprintf("fpga test fail!\n"); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | speed = 10000./temp; | ||
+ | temp = speed * 100; | ||
+ | rt_kprintf("fpga test ok!\n"); | ||
+ | // rt_kprintf("speed : %d.%02dMBytes/s\n",temp/100,temp%100); | ||
+ | } | ||
+ | |||
+ | return RT_EOK; | ||
+ | } | ||
+ | |||
+ | MSH_CMD_EXPORT(spi_write_read_test,fpga); | ||
+ | |||
+ | static int rt_hw_spi_fpga_probe(void) | ||
+ | { | ||
+ | struct rt_spi_configuration cfg; | ||
+ | rt_size_t t_size = 0; | ||
+ | rt_uint8_t send_buffer[5]; | ||
+ | rt_uint8_t recv_buffer[5]; | ||
+ | rt_uint8_t fpga_id; | ||
+ | |||
+ | /* find spi4 device*/ | ||
+ | spi4_device = (struct rt_spi_device *)rt_device_find(FPGA_DEVICE_NAME); | ||
+ | if(spi4_device == RT_NULL) | ||
+ | { | ||
+ | rt_kprintf("ERROR: SPI device %s not found!\n", FPGA_DEVICE_NAME); | ||
+ | return RT_ERROR; | ||
+ | } | ||
+ | |||
+ | /* config spi4 bus */ | ||
+ | cfg.data_width = 8; | ||
+ | cfg.max_hz = 130*1000*1000; | ||
+ | cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_3 | RT_SPI_MSB; | ||
+ | rt_spi_configure(spi4_device, &cfg); | ||
+ | |||
+ | /* get fpga ID*/ | ||
+ | send_buffer[0] = 0x01; | ||
+ | |||
+ | t_size = rt_spi_transfer(spi4_device,send_buffer,recv_buffer,sizeof(send_buffer)); | ||
+ | if(t_size != sizeof(send_buffer)) | ||
+ | { | ||
+ | rt_kprintf("[FPGA] probe fail!"); | ||
+ | return RT_ERROR; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | rt_kprintf("[FPGA] probe ok! ID is 0x%02X\n",recv_buffer[4]); | ||
+ | |||
+ | fpga_id = recv_buffer[4]; | ||
+ | |||
+ | return fpga_id; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | static int rt_hw_spi4_fpga_init(void) | ||
+ | { | ||
+ | __HAL_RCC_GPIOE_CLK_ENABLE(); | ||
+ | |||
+ | /* attach fpga to spi bus */ | ||
+ | rt_hw_spi_device_attach(FPGA_SPI_DEVICE_NAME, FPGA_DEVICE_NAME, GPIOE, GPIO_PIN_4); | ||
+ | |||
+ | /* probe fpga */ | ||
+ | rt_hw_spi_fpga_probe(); | ||
+ | |||
+ | return RT_EOK; | ||
+ | } | ||
+ | |||
+ | INIT_COMPONENT_EXPORT(rt_hw_spi4_fpga_init); | ||
+ | |||
+ | static int fpga(int argc, char **argv) | ||
+ | { | ||
+ | int result = RT_EOK; | ||
+ | |||
+ | if (argc > 1) | ||
+ | { | ||
+ | if(!strcmp(argv[0],"fpga")) | ||
+ | { | ||
+ | if (!strcmp(argv[1], "probe")) | ||
+ | { | ||
+ | if (argc == 2) | ||
+ | { | ||
+ | rt_hw_spi_fpga_probe(); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | rt_kprintf("Bad command. Please enter 'fpga' for help\n"); | ||
+ | } | ||
+ | } | ||
+ | else if (!strcmp(argv[1], "test")) | ||
+ | { | ||
+ | if (argc == 2) | ||
+ | { | ||
+ | spi_write_read_test(); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | rt_kprintf("Bad command. Please enter 'fpga' for help\n"); | ||
+ | } | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | rt_kprintf("Bad command. Please enter 'fpga' for help\n"); | ||
+ | } | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | rt_kprintf("Bad command. Please enter 'eeprom' for help\n"); | ||
+ | } | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | rt_kprintf("Usage: \n"); | ||
+ | rt_kprintf("fpga probe - read fpga id value\n"); | ||
+ | rt_kprintf("fpga test - write & read test fpga\n"); | ||
+ | result = -RT_ERROR; | ||
+ | } | ||
+ | |||
+ | return result; | ||
+ | } | ||
+ | MSH_CMD_EXPORT(fpga, fpga function); | ||
+ | #endif /* BSP_USING_SPI_FPGA */ | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== 4、在board\CubeMX_Config目录下,打开CubeMX_Config.ioc工程。配置SPI4为Full-Duplex Master模式,将GPIO设置为Very High,点击GENERATE CODE。 ==== | ||
+ | |||
+ | {{ :icore4t:iCore4T_RTT_14_7.png?direct |}} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== 5、使用命令scons --target=mdk5,生成MDK5工程,在工程文件stm32h7xx_hal_conf.h中,取消SPI库文件注释。 ==== | ||
+ | |||
+ | {{ :icore4t:iCore4T_RTT_14_6.png?direct |}} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== 6、先将iCore4T_FPGA_17:基于SPI总线的ARM与FPGA通信实验中FPGA程序下载到fpga中。 ==== | ||
+ | |||
+ | |||
+ | ==== 7、将工程编译,烧录,就可以进行FPGA读写测试了。打开终端,选择对应COM口,比特率115200,可以看到系统启动信息,设备列表中有SPI4总线,FPGA设备。执行命令fpga probe探测到FPGA的ID为0x01,执行fpga test进行FPGA读写测试。 ==== | ||
+ | |||
+ | {{ :icore4t:iCore4T_RTT_14_8.png?direct |}} | ||
+ | |||
+ | 至此说明我们的RAM-FPGA通信成功。 | ||
+ | |||
+ | ==== 8、源代码 ==== | ||
+ | |||
+ | 源代码可以稳步这里下载: | ||
+ | |||
+ | 链接:https://pan.baidu.com/s/1fcLU4WaRDlgr0mNYwZj1Yg 提取码:zstq | ||