【Sipeed 高云GW2A FPGA开发板】——ARM Cortex-M0软核处理器_串口打印
[复制链接]
本帖最后由 mars4zhu 于 2022-11-23 19:46 编辑
ARMSOC-3
ARMSOC-3在FPGA中实现了AHB2LED和AHB2UART,即通过ARM Cortex-M0 DesignStart内核,实现对LED的亮灭控制,以及对UART的数据通讯。
4.4.1. 调整Keil软件项目代码
直接打开Keil项目文件并编译,(后续下载到FPGA发现运行异常),分析Keil软件生成的map文件,发现代码所需的HEAP和STACK,都远远超出了内存范围。其内存布局如下:
Exec Addr Load Addr Size Type Attr Idx E Section Name Object
0x00000394 - 0x00000060 Zero RW 112 .bss c_p.l(libspace.o)
0x000003f4 0x00000394 0x0000000c PAD
0x00000400 - 0x00100000 Zero RW 2 HEAP cm0dsasm.o
0x00100400 - 0x00040000 Zero RW 1 STACK cm0dsasm.o
可见HEAP和STACK过大,超过了允许的RAM范围,
-
解决方案为修改代码,在cm0dsasm.s文件中,将Heap_Size和Stack_Size的大小调整如下:
Stack_Size EQU 0x00000100 ; 256Bytes of STACK
AREA STACK, NOINIT, READWRITE, ALIGN=4
Stack_Mem SPACE Stack_Size
__initial_sp
Heap_Size EQU 0x00000100 ; 256Bytes of HEAP
AREA HEAP, NOINIT, READWRITE, ALIGN=4
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
-
同时修改软件代码main.c,符合本开发板的名称,如下:
int main(void) {
int i;
printf("\nWelcome to ARM CM0-DS Example Platform on TangPrimer-20K\n");
printf("\nSend Char from UART\n");
while(1)
{
*(unsigned int*) AHB_LED_BASE = 0x55;
for(i=0;i<100000;i++);
*(unsigned int*) AHB_LED_BASE = 0xAA;
for(i=0;i<100000;i++);
}
}
-
最终生成的内存布局如下:
Execution Region ER_RW (Exec base: 0x00000394, Load base: 0x00000394, Size: 0x00000008, Max: 0xffffffff, ABSOLUTE)
Exec Addr Load Addr Size Type Attr Idx E Section Name Object
0x00000394 0x00000394 0x00000008 Data RW 43 .data retarget.o
Execution Region ER_ZI (Exec base: 0x0000039c, Load base: 0x0000039c, Size: 0x00000264, Max: 0xffffffff, ABSOLUTE)
Exec Addr Load Addr Size Type Attr Idx E Section Name Object
0x0000039c - 0x00000060 Zero RW 112 .bss c_p.l(libspace.o)
0x000003fc 0x0000039c 0x00000004 PAD
0x00000400 - 0x00000100 Zero RW 2 HEAP cm0dsasm.o
0x00000500 - 0x00000100 Zero RW 1 STACK cm0dsasm.o
4.4.2. Keil软件调试
设置Keil软件内置ARM Cortex-M0仿真器,将本项目中AHB2LED和AHB2UART的存储空间设置为可读可写属性,设置断点,然后进入调试,观察AHB2LED和AHB2UART的数据寄存器地址处的数据变化,如图:
4.4.3. 调整FPGA硬件项目代码
原设计是使用Nexys3开发板上的16MB容量的SRAM和Flash,在本开发板上暂无实现如此大容量的存储空间,只能使用FPGA内置的SRAM,因此依然采用ARMSOC-1中的方式,即利用AHB2MEM的例化,由于刚开始并不知道软件代码所需的内存空间大小,只设置了1KB的RAM容量,结果编译出来的代码有3KB多,最终运行异常,FPGA开发板无反应。
-
通过前述Keil软件代码调整,并最终编译后,分析生成的存储空间分布情况,至少需要1.5KB的内存,因此在AHBLITE_SYS.v中,将AHB2MEM例化参数的MEMWIDTH改为12,即2^12 = 4096Byte = 4KB。
//AHBLite Slave
AHB2MEM #(
.MEMWIDTH(12)
) uAHB2MEM (
-
同时需要修改主频,原设计是将Nexys3上的板载100MHz二分频后,以50MHz主频运行,本开发板板载27MHz时钟,无需分频,因此修改如下:
// Nexys3 onboard oscillator: 100MHz
// TangPrimer-20K: 27MHz.
/*
//CLOCK DIVIDER & RESET
reg rCLK;
always @(posedge CLK)
rCLK <= ~rCLK;
assign HCLK = rCLK;
*/
assign HCLK = CLK;
assign HRESETn = RESETn;
-
在AHBL_UART中,波特率是通过对主频50MHz分频得到19200波特率,也需要根据本开发板的27MHz主频进行响应的调整,如下:
//Baudrate = 19200 = 50Mhz/(163*16)
// TangPrimer-20K, 27MHz, Baudrate = 19200 = 27MHz/(88 * 16)
parameter COUNTER_MAX = 88;
assign count_next = ((count_reg == COUNTER_MAX) ? 0 : count_reg + 1'b1);
assign baudtick = ((count_reg == COUNTER_MAX) ? 1'b1 : 1'b0);
-
综合结束后设置引脚分配约束文件,如下:
IO_LOC "RESETn" T10;
IO_PORT "RESETn" PULL_MODE=UP;
IO_LOC "CLK" H11;
IO_PORT "CLK" PULL_MODE=UP;
IO_LOC "LED[7]" P6;
IO_PORT "LED[7]" PULL_MODE=UP DRIVE=8;
IO_LOC "LED[6]" T6;
IO_PORT "LED[6]" PULL_MODE=UP DRIVE=8;
IO_LOC "LED[5]" L16;
IO_PORT "LED[5]" PULL_MODE=UP DRIVE=8;
IO_LOC "LED[4]" L14;
IO_PORT "LED[4]" PULL_MODE=UP DRIVE=8;
IO_LOC "LED[3]" N14;
IO_PORT "LED[3]" PULL_MODE=UP DRIVE=8;
IO_LOC "LED[2]" N16;
IO_PORT "LED[2]" PULL_MODE=UP DRIVE=8;
IO_LOC "LED[1]" A13;
IO_PORT "LED[1]" PULL_MODE=UP DRIVE=8;
IO_LOC "LED[0]" C13;
IO_PORT "LED[0]" PULL_MODE=UP DRIVE=8;
IO_LOC "RsTx" M11;
IO_PORT "RsTx" PULL_MODE=UP DRIVE=8;
IO_LOC "RsRx" T13;
IO_PORT "RsRx" PULL_MODE=UP;
-
完成FPGA综合、布局布线、时序和功耗分析后的资源利用率如下:
4.4.4. 下载到FPGA板运行
最终运行的串口输出结果:
FPGA开发板运行效果:
|