想在项目上使用串口命令行的方式操作工程里的某些线或者获取某些信息,FPGA使用的是Kintex-7,移植开源的letter shell适配MicroBlaze的运行。
开源的letter shell网址:letter-shell
我移植的是2.x的版本,如下图所示。
文章图片
FPGA工程里面主要例化一个Microblaze软核,添加一个uart lite,一个gpio。uart管串口的接收和发送,gpio点LED灯用。还例化了一个up_axi模块,这个模块是ADI的一个开源的模块,可以把AXI Lite接口转成普通的Corebus接口,后面添加用户的读写寄存器比较方便,相对于AXI接口来讲,这个Corebus接口比较方便用户操作,当然也可以用Vivado工具自己定义一个AXI Lite模块来添加一些寄存器进去。我把up_axi做成了一个ip,可以在block design里面调用。
文章图片
下面还是继续讲letter shell的移植吧,letter shell 2.x版本下载下来之后,目录如下所示
文章图片
letter shell的源码修改了shell_cfg.h里几个参数。大概的作用就是在main函数的while(1)循环中调用shelltask函数,shell命令通过list的方式添加而不通过export的方式。
文章图片
Microblaze的SDK工程那边就调用一下hello world的模板,然后添加一些函数进去,这也是主要参考letter shell 2.x里面README的内容。
README里的移植说明如下,
文章图片
我把SDK生成的hello world改成了下面的内容。因为之前试过用export的方式不太行,README里面说用GCC编译要在ld文件里面添加个什么东西,不太会,所以就简单弄了下通过表的方式把命令列出来。
#include
#include "platform.h"
#include "xil_printf.h"
#include "letter-shell-shell2.x/shell_cfg.h"
#include "letter-shell-shell2.x/shell.h"
#include "letter-shell-shell2.x/shell_ext.h"
#include"xparameters.h"
#include"xuartlite.h"
#include"xuartlite_l.h"
SHELL_TypeDef shell;
int ledon(int);
int ledoff(int);
signed char uartRead(char *data)
{
u32 a;
a=XUartLite_GetStatusReg(XPAR_AXI_UARTLITE_0_BASEADDR);
if((a&1)==1)
{
*data=https://www.it610.com/article/XUartLite_RecvByte(XPAR_AXI_UARTLITE_0_BASEADDR);
return 0;
}
else
{
return -1;
}
}void uartWrite(char data)
{
XUartLite_SendByte(XPAR_AXI_UARTLITE_0_BASEADDR,data);
}int ledon(int i)
{
unsigned char data;
switch(i){
case 0x1: data = Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,data|0x1);
printf("led1 is on...\r\n");
break;
case 0x2:data = https://www.it610.com/article/Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,data|0x2);
printf("led2 is on...\r\n");
break;
case 0x3:data = https://www.it610.com/article/Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,data|0x4);
printf("led3 is on...\r\n");
break;
case 0x4:data = https://www.it610.com/article/Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,data|0x8);
printf("led4 is on...\r\n");
break;
case 0x5:data = https://www.it610.com/article/Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,data|0x10);
printf("led5 is on...\r\n");
break;
case 0xff:
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,data|0xff);
printf("all led is on...\r\n");
break;
default:break;
}
return 0;
}int ledoff(int i)
{
int data;
switch(i){
case 1: data = https://www.it610.com/article/Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
if(data&0x01)
{
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,data&0xFE);
printf("led1 is off...\r\n");
}
else
{
printf("led1 is already off...\r\n");
}
break;
case 2:data = https://www.it610.com/article/Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
if(data&0x02)
{
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,data&0xFD);
printf("led2 is off...\r\n");
}
else
{
printf("led2 is already off...\r\n");
}
break;
case 3:data = https://www.it610.com/article/Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
if(data&0x04)
{
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,data&0xFB);
printf("led3 is off...\r\n");
}
else
{
printf("led3 is already off...\r\n");
}
break;
case 4:data = https://www.it610.com/article/Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
if(data&0x08)
{
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,data&0xF7);
printf("led4 is off...\r\n");
}
else
{
printf("led4 is already off...\r\n");
}
break;
case 5:data = https://www.it610.com/article/Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
if(data&0x10)
{
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,data&0xEF);
printf("led5 is off...\r\n");
}
else
{
printf("led5 is already off...\r\n");
}
break;
case 0xff:
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,data&0x00);
printf("all led is off...\r\n");
break;
default:break;
}
return 0;
}unsigned short cmdsize=3;
//cmdsize must matches the commands in cmd_list
SHELL_CommandTypeDef cmd_list[]={
{"clr",shellClear,"clr\t--clear command line"},
{"ledon",ledon,"ledon []\t--0x1~0x5 separate led --0xff all led"},
{"ledoff",ledoff,"ledoff [] \t--0x1~0x5 separate led --0xff all led"},
};
int main()
{
init_platform();
shell.read = uartRead;
shell.write = uartWrite;
shellInit(&shell);
shellSetCommandList(&shell, cmd_list, cmdsize);
while(1){
shellTask(&shell);
}
return 0;
}
用putty串口助手,运行SDK打印信息如下
文章图片
通过命令行控制LED打开
>>ledon 0x1
>>ledon 0x3
>>ledon 0x5
文章图片
【FPGA|Xilinx FPGA 使用Microblaze实现串口命令行】
推荐阅读
- Verilog|if-else(if判断语句和执行语句之间相差1个时钟周期吗(并行执行吗?有优先级吗?))
- #|【数字IC】深入浅出理解AXI协议
- fpga开发|基于FPGA的实时图像边缘检测系统设计(上)
- fpga开发|基于FPGA的实时图像边缘检测系统设计
- 数字IC面经|数字IC笔面试(一)——联发科提前批笔试题记录
- FPGA图像处理及仿真测试|FPGA实现图像二值形态学滤波——腐蚀膨胀
- 【3】7系列FPGA结构|从底层结构开始学习FPGA----MMCM与PLL
- verilog中case,casex,casez的作用(自我总结)
- matlab|FPGA实现sobel边缘检测并Modelsim仿真,与MATLAB实现效果对比