赞
踩
讲师介绍:
培训内容:
//UDP_HW_SPEEDUP-------------------------------------------------------- wire HSEL_temp; assign HSEL_temp = HSEL && (HADDR[31:28] == 4'h7); reg [7:0] test_datai; reg test_dbusy; wire dready; always @(posedge HCLK or negedge SYSRESETn) begin if (~SYSRESETn) begin test_datai <= {8{1'b0}}; test_dbusy <= 1'b0; end else if(dready) begin test_datai <= test_datai + 1'b1; test_dbusy <= 1'b1; end else begin test_datai <= {8{1'b0}}; test_dbusy <= 1'b0; end end assign udp_tpnd = tsmac_tpnd && udp_cs; // UDP SPEEDUP is driven from the AHB generate if (`CORTEXM1_AHB_UDP == 1) begin : gen_udp_hw_speedup_0 udp_hw_speedup u_udp_hw_speedup( .HCLK (HCLK), // system bus clock .HRESETn (SYSRESETn), // system bus reset .datai (test_datai), // source data .dbusy (test_dbusy), // source data valid .dready (dready), // hw_speedup_ready .HSEL (HSEL_temp), // AHB peripheral select .HREADY (HREADY), // AHB ready input .HTRANS (HTRANS), // AHB transfer type .HSIZE (HSIZE), // AHB hsize .HWRITE (HWRITE), // AHB hwrite .HADDR (HADDR), // AHB address bus .HWDATA (HWDATA), // AHB write data bus .HREADYOUT (HREADYOUT_udp),// AHB ready output to S->M mux .HRESP (HRESP_udp), // AHB response .HRDATA (HRDATA_udp), .udp_tdata (udp_tdata), // TSMAC tx data .udp_tstart (udp_tstart), // TSMAC tx start .udp_tpnd (udp_tpnd), // TSMAC tx going .udp_tlast (udp_tlast), // TSMAC tx end .udp_cs (udp_cs) // UDP tx valid ); end else begin : gen_no_udp_hw_speedup_0 assign dready = 1'b0; assign HREADYOUT_udp = 1'b1; assign HRESP_udp = 1'b0; assign HRDATA_udp = {32{1'b0}}; assign udp_tdata = {8{1'b0}}; assign udp_tstart = 1'b0; assign udp_tlast = 1'b0; assign udp_cs = 1'b0; end endgenerate //MEM------------------------------------------------------------------- wire a_wr_en; assign a_wr_en = w_en | ~r_en; wire [31:0] rdata0; assign rdata = rdata0; TEST_RAM u_TEST_RAM ( .wr_data (wdata), // input [31:0] .wr_addr (waddr[7:0]), // input [7:0] .wr_en (a_wr_en), // input .wr_clk (HCLK), // input .wr_clk_en (mem_cs[0]), // input .wr_rst (1'b0), // input .rd_addr (raddr[7:0]), // input [7:0] .rd_data (rdata0), // output [31:0] .rd_clk (HCLK), // input .rd_rst (1'b0) // input );
直接挂在顶层,需要的GPIO直接拖到模块里面就行了。自己建个.v文件把它放到顶层即可。通过定义的地址段,通过软核操作它的地址偏移量,就可以直接操作它了。
为什么不能直接用提供的SPI模块,通过片选控制SPI读写什么的?
本次大赛的目的锻炼总线的方式挂载自己的模块,通过软核控制,这三个东西需要互动起来。如果直接用提供好的GPIO模块去访问自己的东西,相当于直接脱节了,相当于什么都没做。
GPIO_SetBit 实现如下:
void GPIO_SetBit(GPIO_TypeDef* GPIOx,uint32_t GPIO_Pin)
{
GPIOx->DATAOUT |= GPIO_Pin;
}
注意,GPIOx->DATAOUT |= GPIO_Pin;
等价于GPIOx->DATAOUT = GPIOx->DATAOUT | GPIO_Pin;
,即先把GPIOx->DATAOUT
寄存器中的值读出来,然后再与 GPIO_Pin 进行或操作。故,仿真结果不是单纯的0和1的切换,往里面写0写1,就是高低电平,可能默认的DATAOUT 是有数据的,不是预期的高低切换!
全局,临时变量的等的空间分配都是从0x30000000这个地址开始的!
TEST_ADDR = temp_cnt++;
第一次运行到该语句时,TEST_ADDR 的值为 temp_cnt 自加之前的值,temp_cnt的值为自加之后的值。
temp_cnt 是一个全局变量,是系统自动分配的,在数据段地址内随机分配。
TEST_ADDR = 127; 对应地址:0x7000 1000;对应时间:441360000000 fs
temp_cnt = 128; 对应地址:0x3000 0028;对应时间:441460000000 fs
TEST_ADDR = 128; 对应地址:0x7000 1000;对应时间:442060000000 fs
上述的仿真是特殊的地址赋值,评审把结果做成视频,找一些特殊的点,跟C代码结合,如何快速的看到你这个仿真确实是跑起来了!
SD卡模块也要做成一个仿真。参赛队伍比较多,不可能一个个去看,会去抽查5个里面抽1个,进行实实在在的跑,更多的时候是看大家的仿真结果,要更直观的去凸显自己的仿真记过,不仅仅去录视频还要有文档去讲解。
#define TEST_ADDR (*(__IO uint32_t*)(0x70001000)) int temp_cnt = 0; int main(void) { SystemInit(); // TimerInit(); GpioInit(); // UartInit(); // SPIInit0(); // I2CInit(); // SystickInit(); // NVIC_SetPriority(SysTick_IRQn, 1); 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) { // if(key_flag) // { // Delay(1000); // if(!(GPIO_ReadBits(GPIO0)&0x0001)) // { // DEBUG_P("Key interrupt OK.....\r\n"); // } // key_flag = false; // } // Timer_test(timer_counter); GPIO_SetBit(GPIO0,LED_PIN); GPIO_ResetBit(GPIO0,LED_PIN); TEST_ADDR = temp_cnt++; } }
仿真需要使用make_hex128.exe生成3个.data文件(仿真用的);make_hex.exe 生成4个itcm文件(BootLoader用的)。
BootLoader不存在.data
而后放置到仿真的目录下.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval_4_6\simulation
直接覆盖,而后重新运行sim.bat文件
EEPROM地址是8bit位宽,不需要用到16bit,故直接注释掉PANGO_i2c_eeprom.c
读写里面的高8位操作:
接着在PANGO_i2c_eeprom.h
文件中,修改I2C_PageSize
为16
为什么合成sfc文件时,选的.bin文件偏移地址必须是0x000C0000呢?这个是由BootLoader确定的,如下图:
BootLoader工程地址:
.\pgr_FPGA_Cortex-M1_eval\software_design\boot\Cortex-M1_spi_flash_bootloader
BootLoader去引导C语言从FLASH中去读数据,读数据去加载到DDR里,它的起始读地址,是从0xC0000开始的。
APP_BIN_SIZE 大小为409664,即644K = 256K,最大位流为256K。
故没必要修改BootLoader,即时跑LWIP和FreeRTOS,位流大小也够用!
BootLoader打印是看BootLoader起来了没,方便定位是BootLoader问题,还是应用程序问题!
仿真用的BootLoader和实际在板子上跑用的BootLoader是不一样的,也就是说4个ITCM文件不一样!
等功能没问题了,再去改或测试BootLoader。
黑金板下载到FLASH之后需要复位,或者掉电再运行!
上述点不了是因为,黑金的SPI线没有引出来!
片上跑,必须依赖块RAM,块RAM很珍贵!
不带操作系统十几个KB
跑操作系统和LWIP,代码段都有70+KB.
片上资源放不了,加Cache,把代码放到DDR。Cache的原理是:片上开一小块RAM,执行到哪一个段,从DDR里去取,如果命中了,直接在块RAM中去取,如果没有命中,去DDR里去取,地址和数据全部取出来,才能进行下一步处理。
实现SD卡的功能,即便没有挂到软核上去,但是逻辑端已经实现了这个功能。仿真也能跑起来。
0xC0000能不能改?
可以,需要改两个地方
AHB总线使用:
只要看顶层,AHB总线就那么点东西,根据地址去做判断,去做偏移量处理,地址段在哪一段,数据是什么,怎么去处理什么的。
SD接口,怎么分配引脚?
参考UDP加速,总线定义好之后,在模块里例化GPIO就可以了。
黑金开发板SD卡引脚支持的是SPI模式,并不是SDIO模式。
没关系,什么模式。现在大赛需要做的是,通过AHB 总线接口去SD卡,总线怎么去操作,把模块规定一个起始地址,往这个寄存器里面去写数据,去控制SD卡读写。读操作相当于访问了一个SD卡的读操作。
开放的目的是给你们参考,看一下内部一个简单的寄存器读写怎么实现的,外设内部的所有动作都通过这些寄存器实现的。m1通过AHB总线写某个约定好的寄存器,就可以将需要实现的功能发给外设模块,比如m1通过AHB总线写地址为0×00000004寄存器的第一个bit位,这个bit位约定为进行i2c的start操作,外设内部逻辑一旦检测到改bit位有效,就开始造出i2c的是start波形。这个过程就实现了m1完成i2c的start操作
即要把软核和SD卡这个纯逻辑的东西联合
坏区检测思路
每个块都进行一个读写校验,看它有没有错。
不希望大家直接使用现有的SPI接口去访问SD卡!
SD卡仿真要求?
单独写激励,能仿真起来就可以了。能结合软核一起跑,通过软核即C语言,控制寄存器跑起来,这样也是可以的!这样晋级的概率更大!
是的,无法挂。
自己写1个模块,挂载AHB总线上,实现SD卡的读写,这样也是可以的!不一定拿黑金的代码来!只要能实现SD卡的读写,并且挂载AHB总线上,没有用现成的东西,这个就是可以的!
初审不要求LWIP仿真,也没法跑,做TCP/IP的激励也很复杂
这样没有通过网线与PC机交互,算是附加功能。
??
上板的BootLoader工程和仿真的BootLoader文件是不一样的(4个ITCM文件不一样)!分别放在了工程里面!不需要动!在完成了功能之后,再去尝试这些功能!
底下配有说明文档,用的更多的是查核?
存储空间不用担心,使用了CACHE之后,DDR的寻址范围,CACHE都是可以访问的!
ICACHE指令起始地址必须配置为:0x10000000,DDR颗粒映射范围:0x10000000~0x10FFFFFF(16MB)
DCACHE数据起始地址必须配置为:0x30000000,DDR颗粒映射范围:0x30000000~0x3FFFFFFF(256MB)
除了0x10000000前面十几M的代码段外,后面的数据段,全部都是可以映射到DDR,即几百兆的空间都是可以通过软核申请操作的!
对应映射的实际物理地址,映射到了DDR中,实际地址是多少呢?需要通过C语言去把地址读出来,读出来过后,与实际DDR地址对应起来。
数据段地址,在keil中可以通过魔术棒配置为0x30001000,那么0x30000000 ~ 0x30001000之间的地址去哪了呢?它还是实际存在的,实际映射到DDR上,相当于静态存储空间,可以通过C语言直接访问地址的!可参考工程:
.\pgr_FPGA_Cortex-M1_eval\software_design\boot\Cortex-M1_Icache_Dcache_my_mem //参考这个工程,了解如何使用静态存储空间!
这个功能对需要大存储空间的需求特别重要!还可以知道实际的Buffer地址是多少!0x30000000 ~ 0x30001000之间的地址段就是静态的,系统在编译的时候不会编译到这个代码段,而这个代码段的用处就可以访问了。这个就很方便,可以随意使用,与DDR交互,只需要知道与DDR对应的地址是多少就可以了!比如0x30000000对应的DDR地址在xxxx,
上面那个Cortex-M1_Icache_Dcache_my_mem 工程,使用了ICACHE,但是数据段是放到了DTCM上面!只是把DCACHE当成了一个外部设备!起始地址是0x30000000,通过指针的方式直接对它进行读写,8位读写,16位,32位读写都可以!
???
基本要求必须满足,其他看SD卡读写速度,图像传输稳定,图像传输不卡顿,显示很流畅,实时性比较高(前面放一个遮挡物,上位机延时比较短),并不是功能多谁就厉害,还需要看性能!性能越高,得分越高!
GPIO绑定正确,自己去操作偏移量即可!
首先要明白软核和纯逻辑之间的纯逻辑是什么,用C语言怎么去控制纯逻辑代码,通过一个地址,这个地址可以在AHB总线上也可以在APB总线上!现在要求SD模块挂在AHB总线上!通过总线实现,AHB总线地址为0x7000 1000的初始地址,通过C语言往这个地址里面写1个1,你的AHB总线(verilog的input)收到了你的这个数据,把这个地址里面的数据值读出来是1,然后在自己的逻辑里面去做相应的操作!1是实现SD卡的读或写,0x7000 1004这个地址里面写个1,对应SD卡的操作(读或写)。比赛的目的,通过C语言,通过总线地址,去控制SD卡外设的动作!
本身纯逻辑就可以做这个事情,软核下发指令去做这个事情!
首先要想成功编译BootLoader工程,做如下修改:
解决方法:修改堆栈空间,默认分配的很大!魔术棒里面的IROM1和IRAM1分配的很小!
Stack_Size EQU 0x00001000
Heap_Size EQU 0x00001000
改为:
Stack_Size EQU 0x00000100
Heap_Size EQU 0x00000100
注意上图中的,Use MircroLIB勾不要去掉,下面的IROM1和IRAM1默认就行!
上面的配置之后,已经可以正常编译BootLoader工程了,仿真和上板的BootLoader工程区别即main.c
中的SIMULATION
宏有没有打开,打开就是仿真,不打开就是上板!
#define SIMULATION
仿真不需要引导过程,即不需要从SPI-FLASH中把数据读出来进而写入DDR。因为我们是把3个.data文件数据直接放到了DDR里,故省略了这样一个过程!
BootLoader只要能跑起来,代码量没有超过256K,就真的没有必要去改!BootLoader仅仅只是个引导,BootLoader的作用是把你的应用程序加载起来!
应用程序里面完全没有必要勾选#RUN2,即make_hex.exe生成的4个ITCM文件是没有用的!不需要去关心ITCM文件,只需要关系bin文件即可!
1、软核本身的仿真,直观的看到软核跑起来!
2、SD卡的纯逻辑代码仿真,硬件代码已经初步实现,只差上板。或者更进一步SD卡与软核的通过C语言联合仿真。
更好的方式,是上位机上的按键,通过LWIP下发指令等!使用开发板上的物理按键也是可以的,上位机也是需要自己写的,界面功能!
没有标明外设名称的中断,表示软核本身的,暂时是没有用到的!
AHB总线基地址为0x4000 0000,现有的外设到了0x4900 0000,其后的0x4A00 0000 ~ 0x4F00 0000都是可以用的!
UDP加速模块的基地址为:0x70000000
一共用到了0x20,剩余的是都可以用的!即0x7000 0020之后的都可以用!
没有问题!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。