当前位置:   article > 正文

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

pgl22g 软核

导读:本节将以一个简单的 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
  • 1
  • 输出时对应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;
...

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 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时,你猜哪个灯会亮呢?

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/569246
推荐阅读
相关标签