USMART 调试组件由ALIENTEK 开发提供,功能类似 linux 的 shell(RTT 的 finsh 也属于此类)。
USMART 最主要的功能就是通过串口调用单片机里面的任何函数,并执行。因此,你可以随意更改函数的输入参数(支持数字 (10/16进制,支持负数)、字符串、函数入口地址等作为参数),单个函数最多支持 10 个输入参数,并支持函数返回值显示,对我们调试代码是很有帮助的。
USMART是用于STM32上的,由于其方便调试,楼主将其移植到FPGA中,当然要首先在FPGA中添加一个CPU核(话说不这样怎么写C语言。。。)使用的FPGA为SPARTAN6,晶振为50MHZ。在此写下移植过程分享给大家。 先上图,串口调试助手发送函数让LED切换。
代码工程结构如下图(感谢原子对我学习stm32的帮助,有些习惯受其影响较大):
第一步:新建delay.c和delay.h文件。
delay.c里主要为定时器0初始化和中断函数。定时器0主要作USMART的扫描函数的100ms的定时。
delay.c里还写里一个简单的延时函数。delay.c里的#include "usmart.h"为原子的usmart提供的文件。
delay.h里主要是函数声明。
delay.c具体代码如下:
- /***************************** Include Files *********************************/
- #include "delay.h"
- //#include "led.h"
- u32 timer0_num=0;
- /**********************************************************************
- ***********************************************************************/
- void timer_int_handler(void * baseaddr_p)
- {
- unsigned int csr;
- csr = XTmrCtr_GetControlStatusReg(XPAR_AXI_TIMER_0_BASEADDR,0); // read control/status register
- if(csr &XTC_CSR_INT_OCCURED_MASK) // if interrupt is occurred
- {
- timer0_num++;
- usmart_dev.scan();
- if(timer0_num==1000)
- {
- timer0_num=0;
- }
- }
- XTmrCtr_SetControlStatusReg(XPAR_AXI_TIMER_0_BASEADDR,0, csr); //clear interrupt indication
- }
- /**********************************************************************
- ***********************************************************************/
- void Timer0_init()
- {
- init_platform();
- XIntc_RegisterHandler(XPAR_INTC_0_BASEADDR, //register timer0 interrupt and handler process
- XPAR_AXI_INTC_0_AXI_TIMER_0_INTERRUPT_INTR,
- (XInterruptHandler) timer_int_handler,
- (void *)XPAR_AXI_TIMER_0_BASEADDR);
-
- microblaze_enable_interrupts(); //enable microblaze interrupt
- XIntc_MasterEnable(XPAR_INTC_0_BASEADDR); //enable interrupt 0
- XIntc_EnableIntr(XPAR_INTC_0_BASEADDR, XPAR_AXI_TIMER_0_INTERRUPT_MASK); //enable timer0 interrupt
- XTmrCtr_SetLoadReg(XPAR_AXI_TIMER_0_BASEADDR, 0, 10000); //set timer0 reload value 0.2mS
- XTmrCtr_EnableIntr(XPAR_AXI_TIMER_0_BASEADDR, 0); //enable timer0 generate interrupt signal
- //set timer0 work mode and start counter
- XTmrCtr_SetControlStatusReg(XPAR_AXI_TIMER_0_BASEADDR, 0, XTC_CSR_ENABLE_TMR_MASK |
- XTC_CSR_ENABLE_INT_MASK |
- XTC_CSR_AUTO_RELOAD_MASK |
- XTC_CSR_DOWN_COUNT_MASK);
- }
- /**********************************************************************
- ***********************************************************************/
- void delayms(unsigned int x)
- {
- unsigned int i,j;
- while(x--)
- {
- for(j = 0;j < 10;j ++)
- {for(i = 0;i < 500;i ++);}
- }
- }
复制代码
delay.h具体代码如下:
- #ifndef __DELAY_H__
- #define __DELAY_H__
- #include "xparameters.h"
- #include "xintc.h"
- #include "xtmrctr.h"
- #include "mb_interface.h"
- #include "platform.h"
- #include "usmart.h"
- void timer_int_handler(void * baseaddr_p);
- void Timer0_init();
- void delayms(unsigned int x);
- #endif
复制代码
第二步:新建uart.c和uart.h文件。
uart.c里主要是串口的初始化和串口中断函数,这里要特别注意,理解后再向里面移植,否则会导致莫名其妙的情况。串口中断函数结构参照usmart接口要求来写。
uart.h里主要是参数设定和函数声明。
uart.c具体代码如下:
uart.h具体代码如下:
- #ifndef __UART_H__
- #define __UART_H__
- /***************************** Include Files *********************************/
- #include "xparameters.h"
- #include "xuartlite.h"
- #include "xuartlite_l.h"
- //#include "platform.h"
- #include "xintc.h"
- #include "xil_exception.h"
- #include "types.h"
- /************************** Constant Definitions *****************************/
- /*
- * The following constants map to the XPAR parameters created in the
- * xparameters.h file. They are defined here such that a user can easily
- * change all the needed parameters in one place.
- */
- #define UARTLITE_DEVICE_ID XPAR_UARTLITE_0_DEVICE_ID
- #define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
- #define UARTLITE_INT_IRQ_ID XPAR_INTC_0_UARTLITE_0_VEC_ID
- /*
- * The following constant controls the length of the buffers to be sent
- * and received with the UartLite device.
- */
- #define TEST_BUFFER_SIZE 100
- #define UART_REC_LEN 200
- int Uart0_init(void);
- int UartLiteIntr(u16 DeviceId);
- int SetupInterruptSystem(XUartLite *UartLitePtr);
- void uart0_rev_handler(void);
- void SendHandler(void *CallBackRef, unsigned int EventData);
- void RecvHandler(void *CallBackRef, unsigned int EventData);
- #endif
复制代码
第三步:添加usmart源码,原子提供的共有5个文件,分别为usmart.c、usmart.h、usmart_config.c、
usmart_str.c和usmart_str.h。
usmart.h、usmart_str.c基本不需要改动。
usmart_str.h里把#include "stm32f4xx.h"删掉,替换为#include "delay.h"即可。
usmart_config.c是用户自定义,用户添加自己需要调试的函数。
重点是对usmart.c的修改。
1.删掉#include "usart.h"和 #include "sys.h" ,添加#include "uart.h"
2.添加外部参数声明:
extern u8 UART_RX_BUF[UART_REC_LEN];
extern u16 UART_RX_STA;
extern u32 timer0_num;
3.替换void usmart_reset_runtime(void)函数里的内容
替换为:
timer0_num=0;
usmart_dev.runtime=0;
4.替换u32 usmart_get_runtime(void)函数里的内容
替换为:
usmart_dev.runtime+=timer0_num;
return usmart_dev.runtime; //·µ»Ø¼ÆÊýÖµ
5.删掉void TIM4_IRQHandler(void)函数(usmart_dev.scan();已写在delay.c定时器0中断里),
删掉void Timer4_Init(u16 arr,u16 psc)函数。
6.修改void usmart_init(u8 sysclk)函数,要去掉形参,要记得在h文件函数声明里做对应修改,就是说要改做这样void (*init)(void);//扫描。
- void usmart_init(void)
- {
- #if USMART_ENTIMX_SCAN==1
- Timer0_init();
- #endif
- usmart_dev.sptype=1; //十六进制显示参数
- }
复制代码
- void usmart_reset_runtime(void)
- {
- timer0_num=0;
- usmart_dev.runtime=0;
- }
复制代码
至于usmart_config.c的修改我也提供一个范例好了:
- #include "usmart.h"
- #include "usmart_str.h"
- ////////////////////////////用户配置区///////////////////////////////////////////////
- //这下面要包含所用到的函数所申明的头文件(用户自己添加)
- #include "delay.h"
- #include "led.h"
- //#include "sys.h"
- //#include "lcd.h"
-
- //extern void led_set(u8 sta);
- //extern void test_fun(void(*ledset)(u8),u8 sta);
- //函数名列表初始化(用户自己添加)
- //用户直接在这里输入要执行的函数名及其查找串
- struct _m_usmart_nametab usmart_nametab[]=
- {
- /*
- #if USMART_USE_WRFUNS==1 //如果使能了读写操作
- (void*)read_addr,"u32 read_addr(u32 addr)",
- (void*)write_addr,"void write_addr(u32 addr,u32 val)",
- #endif
- (void*)delay_ms,"void delay_ms(u16 nms)",
- (void*)delay_us,"void delay_us(u32 nus)",
- (void*)LCD_Clear,"void LCD_Clear(u16 Color)",
- (void*)LCD_Fill,"void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)",
- (void*)LCD_DrawLine,"void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)",
- (void*)LCD_DrawRectangle,"void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2)",
- (void*)LCD_Draw_Circle,"void Draw_Circle(u16 x0,u16 y0,u8 r)",
- (void*)LCD_ShowNum,"void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size)",
- (void*)LCD_ShowString,"void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p)",
- (void*)LCD_Fast_DrawPoint,"void LCD_Fast_DrawPoint(u16 x,u16 y,u16 color)",
- (void*)LCD_ReadPoint,"u16 LCD_ReadPoint(u16 x,u16 y)",
- (void*)LCD_Display_Dir,"void LCD_Display_Dir(u8 dir)",
- (void*)LCD_ShowxNum,"void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode)",
- (void*)led_set,"void led_set(u8 sta)",
- (void*)test_fun,"void test_fun(void(*ledset)(u8),u8 sta)",
- */
- (void*)delayms,"void delayms(unsigned int x)",
- (void*)led_on,"void led_on(u32 led_num)",
- (void*)led_off,"void led_off(u32 led_num)",
- };
- ///////////////////////////////////END///////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////////
- //函数控制管理器初始化
- //得到各个受控函数的名字
- //得到函数总数量
- struct _m_usmart_dev usmart_dev=
- {
- usmart_nametab,
- usmart_init,
- usmart_cmd_rec,
- usmart_exe,
- usmart_scan,
- sizeof(usmart_nametab)/sizeof(struct _m_usmart_nametab),//函数数量
- 0, //参数数量
- 0, //函数ID
- 1, //参数显示类型,0,10进制;1,16进制
- 0, //参数类型.bitx:,0,数字;1,字符串
- 0, //每个参数的长度暂存表,需要MAX_PARM个0初始化
- 0, //函数的参数,需要PARM_LEN个0初始化
- };
- 总的来说,由于原工程的代码写的实在是精彩,所以移植其实是很顺利的,如果依旧不是很清楚可以去看我师弟的帖子,他的叙述比我的详细得多51单片机移植ALIENTEK的USMART调试组件
复制代码
|