【第五届集创赛备赛】五、紫光FPGA Cortex-M1 SoC快速上手

文章目录

  • 一、原材料准备
  • 二、编译应用程序的keil工程,得到bin文件
    • 2.1、准备led应用程序对应的keil工程
    • 2.2、设置ROM和RAM的起始地址和大小
    • 2.3、配置输出 bin 文件
    • 2.4、全编译工程,输出bin文件
    • 2.5、下载程序到FLASH中
    • 2.6、连接串口,查看打印信息
  • 三、实验原理分析
    • 3.1、知识储备
    • 3.2、代码分析
  • 四、仿真
    • 4.1、重新编译仿真库
    • 4.2、拷贝unsim文件夹至RTL工程的Simulation目录下
    • 4.3、拷贝应用工程生成的三个文件`mem_xxx.dat`文件至RTL工程的Simulation文件夹
  • 五、常见问题及解决方法
    • 5.1、modelsim 仿真报错`** Error: (vish-42) Unsupported ModelSim library format…`
    • 5.2、使用I2C 驱动 EEPROM 报错
    • 5.3、网络相关设置
  • 六、其他小知识

导读:本节将以一个简单的 LED Demo 为例,详细介绍基于PGL22G 的 Cortex-M1 软核开发流程。

一、原材料准备

工欲善其事必先利其器,在正式开跑软核之前,还需要准备一下软件和Demo工程,清单如下:

  • Keil V5.15.0(建议与官方测试版本保持一致)
  • ARM.CMSIS.5.6.0.pack(Cortex-M1的固件库)
  • PDS 2020.3(建议与官方测试版本保持一致)
  • pgr_FPGA_Cortex_M1_PGL22_324_eval.rar(钉钉群下载)
  • pgr_FPGA_Cortex-M1_eval_v1_2.rar(钉钉群下载)

钉钉群下载的两个文件解压后,放置到没有中文和空格的路径下,然后将pgr_ARM_Cortex_M1_PGL22_324_eval文件夹放置到pgr_FPGA_Cortex-M1_eval文件夹下的rtl_design目录里,层级结构如下图所示:

在这里插入图片描述

:下文若要对应到pgr_ARM_Cortex_M1_PGL22_324_eval所在目录,会直接写成:.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval的形式。

二、编译应用程序的keil工程,得到bin文件

2.1、准备led应用程序对应的keil工程

LED应用程序对应的keil工程,位于:.\pgr_FPGA_Cortex-M1_eval\software_design\module_design\Cortex-M1_led目录下。进入其子目录PROJECT,双击cortex_M1_led.uvprojx即可打开keil工程,如下图所示:

在这里插入图片描述

2.2、设置ROM和RAM的起始地址和大小

PGL22G Cortex-M1软核的ROM和RAM设置方式有两种:

  • 在不使用 CACHE 的 Cortex M1 中, ITCM 作为 ROM(起始地址为 0x00000000), DTCM 作为 RAM(起始地址为 0x20000000),大小根据用户实际需求进行设置。
  • 在使用 CACHE 的 Cortex M1 中, ICACHE 作为 ROM(起始地址为 0x10000000), DCACHE 作为 RAM(起始地址为 0x30000000),大小根据用户实际需求进行设置。

我们使用CACHE,故ROM和RAM地址设置为上述第二种,具体配置方式如下所示。

①、点击工具栏的魔术棒选项:
在这里插入图片描述

②、选择Target,设置ROM和RAM起始地址和大小:

  • IROM1:起始地址:0x10000000、大小:0x1000000
  • IRAM1:起始地址:0x30000000、大小:0x100000

在这里插入图片描述

  • ICACHE 指令起始地址必须配置为:0x1000 0000DDR 颗粒映射范围 0x0000 0000-0x00FF FFFF(即最大:16MB - 0x100 0000);
  • DCACHE 数据起始地址必须配置为: 0x3000 0000DDR 颗粒映射范围 0x0100 0000-0x0FFF FFFF(即最大:256MB - 0x10000 0000)。
  • 不能超过这个映射范围,否者会出错。

2.3、配置输出 bin 文件

Cortex-M1 软件编程设计通过:

  • Run #1 操作, 将 axf 文件转换为 bin 文件格式并输出;
  • Run #2 操作, 使用 make_hex.exe 工具将 bin 文件转换为 4ITCM 文件格式并输出。

关于ITCM要说的几点

  • 使用 CACHE 的 Cortex M1 中,需要引导应用程序(即通过 Bootloader 工程产生的 itcm0itcm1itcm2itcm3 4个文件)才能将应用工程指令(即由本节的LED工程编译生成的 BIN 文件) 装载到 DDR 颗粒中并实现地址跳转
  • 所以,上述的 Run #1 操作主要是为我们的LED应用工程产生bin文件,而Run #2操作是为我们的Bootloader 引导工程产生4个ITCM文件。为了让应用工程和引导工程可以复用同一个keil模板,就没有在应用工程中特别地去掉Run #2 操作,同理也没有在引导工程中特别地去掉Run #1 操作。(后面做仿真会用在应用工程中修改 Run #2
  • 本节是生成应用工程的bin文件,是不是下一节就是生成引导工程的4个ITCM文件?不!4个ITCM文件我们直接使用pgr_FPGA_Cortex_M1_PGL22_324_eval这个PDS工程自带的即可!(自带的4个ITCM文件位置:.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\pnr

继续回到正题,输出 bin 文件的具体配置方式如下所示。

①、点击工具栏的魔术棒选项:
在这里插入图片描述

②、选择User,设置Run #1和Run #2的值:

  • Run #1:D:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin -o cortex_M1_led.bin .\Objects\cortex_M1_led.axf(第一路径参数需要设置为自己的keil5安装路径
  • Run #2:make_hex.exe cortex_M1_led.bin

在这里插入图片描述

2.4、全编译工程,输出bin文件

①、点击工具栏的全编译按钮,如下图所示:
在这里插入图片描述

②、全编译完成后如下图所示:

在这里插入图片描述
③、在keil工程目录下的Projet中,即可看到输出的cortex_M1_led.bin文件,如下图所示:

在这里插入图片描述

将生成的cortex_M1_led.bin文件拷贝到pgr_ARM_Cortex_M1_PGL22_324_eval这个PDS工程的pnr\generate_bitstream目录下,如下图所示:

在这里插入图片描述

2.5、下载程序到FLASH中

①、双击.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\pnr路径下的ARM_M1_SoC_Top.pds,打开官方提供的PDS工程。(第一次打开可能需要等待片刻~)

在这里插入图片描述

②、生成sbit文件

右击左侧Flow栏中的Generate Bitstream选项,选择Rerun All,而后会弹出确认窗口,点击Yes即可。

:我的整个编译过程大概持续了8min 50s

在这里插入图片描述

在这里插入图片描述

补充:使用带 CACHECortex M1 SoC 工程时,一定要将 Bootloader 生成的 itcm0itcm1itcm2itcm3 4个文件放入该 PDS 工程的pnr目录下,与 RTL 工程一起编译生成sbit文件,否则将不能实现应用程序的引导与地址跳转。(BootLoader工程生成的itcm0~itcm34个文件,我们直接用官方提供在PDS工程自带的即可,我们不需要太关心这个,应该把重点放在应用工程的bin文件上!)

③、连接硬件,把 JTAG 下载器和开发板连接,然后开发板上电(下图为开发板的硬件连接图)。

在这里插入图片描述

④、单击界面中的“Configuration”按钮,作用是下载程序。

在这里插入图片描述

⑤、在弹出的界面中的单击Boundary Scan”,然后在右侧空白区单击右键选择Scan Device”;

在这里插入图片描述

⑥、在扫描到 JTAG 设备后会弹出如下对话框,并按如下加载.sbit 文件即可,然后可以看到左侧显示了要加载的文件

在这里插入图片描述
在这里插入图片描述

⑦、将sbit文件转换为sfc文件

对于PGL22G这款FPGA而言:

  • 直接下载到FPGA的程序文件格式为:.sbit,该种方式掉电会丢失
  • 间接下载到FLASH的程序文件格式为:.sfc,该种方式掉电不会丢失

但是我们肯定不能直接下载sbit文件了,一方面是由于其程序掉电会丢失,另一方面是由于此时我们还没有将应用程序产生的bin文件加载进来!而sfc文件除了由sbit文件转换而成,还可以将sbitbin文件拼接在一起转换成sfc文件,转换方式如下所示:

选择菜单"Operations“下”Convert File"进行文件转换。

在这里插入图片描述
然后弹出如下界面,依次设置:

  • FLASH厂家、型号和读模式:黑金开发板用到的是 WINBONDW25Q128Q这款FLASH,Flash Read Mode 选择 SPI X4, 24-bit address
  • sbit 文件起始地址和路径:起始地址为:0,sbit文件在:.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\pnr\generate_bitstream\m1_soc_top.sbit
  • bin文件使能、起始地址和路径:勾选Load User Data File选项,起始地址为:000C0000,bin文件在:.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\pnr\generate_bitstream\cortex_M1_led.bin

设置完成后如下图所示,点击 OK 即可转换;

在这里插入图片描述
转换成功弹出如图所示对话框,点击OK即可。

在这里插入图片描述

⑧、下载sfc文件到FLASH中

选中右侧的PANGO方块,右击会弹出下拉菜单并选择"Scan outer Flash"。
在这里插入图片描述
选择已生成的 sfc 文件,单击 Open;
在这里插入图片描述

可以看到界面中有了 flash 器件,选中“Outer Flash”方块并右击选择菜单中“Program...

在这里插入图片描述
弹出正在编程的进度界面,flash 编程完成后进度界面自动消失。

在这里插入图片描述
至此,程序烧写完毕。

2.6、连接串口,查看打印信息

①、连接板载UART串口,如下图所示:
在这里插入图片描述

②、打开串口助手,选择合适的COM口,设置波特率115200,重启开发板,观察打印信息

:如找不到串口,注意查看CP2102驱动是否安装成功!

串口输出内容,如下图所示:

在这里插入图片描述

注意观察底板的LED2,间隔闪烁…

在这里插入图片描述

若与上述实验现象一致,则证明实验成功~

三、实验原理分析

3.1、知识储备

首先,先来了解下 M1_soc_top.v 中的信号绑定关系:

  • M1_soc_top.v 中的 gpio_in0 绑定了FPGA管脚P17,对应底板按键 KEY3
  • M1_soc_top.v 中的 gpio_in1 绑定了FPGA管脚L12 对应底板按键 KEY4
  • M1_soc_top.v 中的 rst_key 绑定了FPGA管脚V12 对应底板按键 KEY2
  • M1_soc_top.v 中的 LED[3:0] 分别绑定FPGA管脚U10 V10 U11 V11,对应底板LED[3:0]

另外需要知道,Cortex-M1软核的GPIO模块提供了一组 16 个 I/O 的通用输入输出:

  • 输入时对应M1_soc_top.v 中的verilog代码为:
.p0_in             ({{14{1'b0}}, gpio_in1, gpio_in0}),          // GPIO 0 inputs
  • 输出时对应M1_soc_top.v 中的verilog代码为:
.p0_out            (p0_out),         // GPIO 0 outputs
.p0_outen          (p0_outen),       // GPIO 0 output enables...
assign LED[1:0]    = p0_outen[1:0]  & p0_out[1:0];
assign LED[2]      = ddrc_init_done;
assign LED[3]      = heart_beat_led;
...

3.2、代码分析

打开LED应用工程中的main.c文件,我们就从主函数来一点点分析。

...
#define LED_PIN			GPIO_Pin_1
...
int main(void)
{SystemInit();GpioInit();while(1){GPIO_SetBit(GPIO0,LED_PIN);Delay(DELAY_CNT);GPIO_ResetBit(GPIO0,LED_PIN);Delay(DELAY_CNT);}
}
  • SystemInit 对GPIO寄存器进行初始化(赋0)操作,同时设置系统时钟为125M。
  • GpioInit 对第0组GPIO的第1个管脚进行配置,设置为输出模式,且为普通IO,不设置中断。
  • GPIO_SetBit 第0组GPIO的第1个管脚输出1。
  • GPIO_ResetBit 第0组GPIO的第1个管脚输出0。
  • Delay 是通过for循环计数的方法进行延时,具体时间未知。

对第0组GPIO的第1个管脚输出控制,对应到 M1_soc_top.v 中的代码为:assign LED[1:0] = p0_outen[1:0] & p0_out[1:0];。即当 GPIO_0_1 输出 0 时,p0_outen 的第1位为1,p0_out 的第1位为0,相与操作后LED的第1位为0,对应的LED1会点亮(低电平点亮)。

怎么样,有没有茅塞顿开的感觉,这不是又回到了STM32的感觉了嘛!当你把LED_PIN这个宏定义改为GPIO_Pin_0时,你猜哪个灯会亮呢? 😃 😃 😃 😃

四、仿真

Cortex M1 SoC 的硬件仿真平台采用的是无 Boot 的仿真方法,即跳过从 SPI-FLASH 中加载指令到 DDR 颗粒的过程,直接将所需指令初始化就进 DDR 颗粒的预定空间中,当系统初始化完成后就可进行指令与数据的加载。可实现指令与数据快速仿真,利于用户进行逻辑功能的快速验证与开发。

4.1、重新编译仿真库

打开 Tools -> Compile Simulation Libraries

在这里插入图片描述

设置Simulator Executable Path 为:

D:/modeltech64_10.6d/win64

然后点击Compile(大概需要2min),整个过程如下图所示。
在这里插入图片描述

编译过程,如下图所示:
在这里插入图片描述

编译成功,如下图所示:

在这里插入图片描述

4.2、拷贝unsim文件夹至RTL工程的Simulation目录下

.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\pnr\pango_sim_libraries中的 usim 文件夹拷贝至 .\pgr_FPGA-Cortex_M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\simulation下,如下图所示。

在这里插入图片描述

4.3、拷贝应用工程生成的三个文件mem_xxx.dat文件至RTL工程的Simulation文件夹

①、修改应用工程程序

要生成mem_xxx.dat文件,首先需要修改好我们想要仿真的应用工程程序,打开.\pgr_FPGA_Cortex-M1_eval\software_design\boot下的Cortex-M1_Icache_Dcache_Demo工程,修改main.c中的内容如下:

#define TEST_ADDR (*(__IO uint32_t*)(0x70001000))
int temp_cnt = 0;int main(void)
{SystemInit();GpioInit();						WatchDogInit(WATCH_DOG,2);									DEBUG_P("PANGO Cortex-M1 Start Run......\r\n");DEBUG_P("JEDEC  id = 0x%x\n",SFLASH_ReadJEDEC_ID());while(1){GPIO_SetBit(GPIO0,LED_PIN);GPIO_ResetBit(GPIO0,LED_PIN);TEST_ADDR = temp_cnt++;//		temp_cnt++;
//		TEST_ADDR = temp_cnt * 2;}
}

②、生成xxx.dat文件

为了节约硬件仿真时间,就需要对 DDR 颗粒模型进行初始化赋值操作,即跳过引导过程(无boot),因此需要利用 make_hex128.exe 可执行文件,生成 DDR 颗粒模型初始化所需的xxx.dat文件。

生成方法如下:

  • i、打开应用程序的keil工程,点击魔术棒,选择User,将Run #2原有的值:make_hex.exe cortex_M1_demo.bin,设置为:make_hex128.exe cortex_M1_demo.bin,如下图所示:

在这里插入图片描述

注:这里顺带提一下keil工程中的代码段和数据段设置,如下图所示:
在这里插入图片描述
哦对了,别忘了把 Run #1 中的keil路径修改为自己的keil路径,我的设置内容为:D:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin -o cortex_M1_demo.bin .\Objects\cortex_M1_demo.axf

  • ii、接着点击keil工程的全编译按钮,即可把bin文件转化为如下图所示的 mem_addr.datmem_data.datmem_used.dat 3个文件

在这里插入图片描述

在这里插入图片描述

  • iii、复制mem_xxx.dat文件至RTL工程的Simulation文件夹下

即将.\pgr_FPGA_Cortex-M1_eval\software_design\boot\Cortex-M1_Icache_Dcache_Demo\PROJECT目录下的mem_xxx.dat文件,拷贝至.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\simulation目录下,如下图所示:

在这里插入图片描述

③、运行仿真

双击.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\simulation目录下的sim.bat批处理文件,开始仿真。

在这里插入图片描述

在这里插入图片描述

④、仿真分析

注:需要等待一段时间,等软核跑起来,才会运行到我们的main函数,我这里是仿了 600_000_000_000 fs

keil 应用工程实现的功能是将 0x7000_1000 这个地址的数据实现自加,我们通过波形验证一下是否是这样。

首先找到 HADDR 信号 和 HWDATA 信号。

HADDR 信号颜色设置为红色,方便观察波形,如下图所示:
在这里插入图片描述
在这里插入图片描述

接着将 HWDATA 信号数据格式设置为十进制,如下图所示:
在这里插入图片描述

找到任意一个0x7000_1000出现的位置,如下图所示,此时HWDATA的值为 221 。
在这里插入图片描述

继续寻找下一个0x7000_1000出现的位置,如下图所示,可以看到HWDATA的值为 222 。

在这里插入图片描述

不难得出,实验波形符合预期现象。

注:这里再顺便提一下,两个 0x7000_1000 地址出现的位置之间,0x3000_0028地址处的数据也为222,这并非巧合,而是我们对应的temp_cnt变量的地址,由于我们的keil设置数据段为0x3000_0000,所以temp_cnt变量的地址为0x3000_0000开头!
在这里插入图片描述

五、常见问题及解决方法

5.1、modelsim 仿真报错** Error: (vish-42) Unsupported ModelSim library format...

# Error loading design
# Error: Error loading design 
#        Pausing macro execution 
# MACRO ./sim.tcl PAUSED at line 11
# ** Error: (vish-42) Unsupported ModelSim library format for "E:/Linux Development/PGL22G-Board/1/pgr_FPGA_Cortex-M1_eval/rtl_design/pgr_ARM_Cortex_M1_PGL22_324_eval/simulation/usim". (Format: 4)

解决办法:

  • 重新编译仿真库!

5.2、使用I2C 驱动 EEPROM 报错

解决办法:

  • PANGO_i2c_eeprom.h中的I2C_PageSize宏定义大小改为16
  • main.c中的DATA_LEN宏定义改为10,小于16才可以

5.3、网络相关设置

板子IP:192.168.0.2
板子MAC:00-0A-35-01-FE-C0

电脑IP:192.168.0.3
电脑MAC:40-8D-5C-64-65-3B

#define MAC_ADDR0   			0x00U
#define MAC_ADDR1   			0x0AU
#define MAC_ADDR2   			0x35U
#define MAC_ADDR3   			0x01U
#define MAC_ADDR4   			0xFEU
#define MAC_ADDR5   			0xC0U#define DEST_IP_ADDR0   		192
#define DEST_IP_ADDR1   		168
#define DEST_IP_ADDR2   		0
#define DEST_IP_ADDR3   		3#define DEST_PORT       		5001/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
#define IP_ADDR0   				192
#define IP_ADDR1    			168
#define IP_ADDR2    			0
#define IP_ADDR3    			2/*NETMASK*/
#define NETMASK_ADDR0   		255
#define NETMASK_ADDR1    		255
#define NETMASK_ADDR2    		255
#define NETMASK_ADDR3    		0/*Gateway Address*/
#define GW_ADDR0    			192
#define GW_ADDR1    			168
#define GW_ADDR2    			1
#define GW_ADDR3    			1

keil工程配置:
在这里插入图片描述
IROM1:0x100000000x100000
IRAM1:0x308000000x8000000

六、其他小知识

Cortex-M1软核包含较多宏文件,但CM1_OPTION_DEFS为关键宏文件,涉及系统参数与功能模块的使能配置。换句话说,要内核支持某个模块,需要在RTL代码中作相应的配置,即在cm1_option_defs.v里的某些宏需要打开或关闭!

  • 位置:.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\src\m1_core\cm1_option_defs.v

Cortex M1 SoC 的系统时钟为125Mhz,内置软复位功能以及使用 I/DCACHE 加载指令/数据方式,将所有外设全覆盖使用,包括Bootloader在线调试功能。

带有Cache的设计分为Bootloader部分和应用程序部分,其中Bootloader放置在片上ITCM中,即上电开始运行,而应用程序部分则通过Bootloader从Flash空间加载至DDR颗粒中, 当初始化完成后, CortexM 1软核配合I/DCACHE实现应用程序的执行。

注意:Bootloader程序无需用户编写,用户只需关心应用程序设计即可。通过PDS Configuration插件工具,将应用工程所编译的BIN文件(PGL22平台起始地址为0x000C0000) 与sbit数据流文件拼接,并利用同创cable直接下载到Flash芯片中。此后,板卡上电,当FPGA数据流文件加载完毕后, Bootloader将会自动将Flash空间的指令数据搬运至DDR颗粒中,完成指令初始化操作。

Cortex-M1 SoC的系统时钟默认是接在DDR的axi_clo0上的,如果不使用DDR设备,需要在cm1_option_defs.v中取消注释'#define UNCACHE将系统时钟切换到外部PLL时钟clkout0上。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平