admin 发表于 2022-6-19 16:47:17

【zynq课程笔记】【裸机】【第9课 】【裸机程序调试方法】

更多课程笔记请查看:【zynq裸机编程课程笔记合集】
http://www.corecourse.cn/forum.php?mod=viewthread&tid=29095



在上一节课呢,我们是带领大家一起学习了基于SDK硬件驱动库的编程方法。课程中所用到的那样一个程序呢非常简单,我也是事先编写好了程序,没有现场带领大家一步一步去写。但是,对于大家自己,如果大家自己接到一个任务,要编写一个程序以实现相应的功能。那么,在编写程序的过程中,可能由于事先考虑不周,总会存在一些这样那样的问题,导致程序无法实现想要的功能,那么当程序无法实现功能的时候,如何来分析自己的程序?如何来找出自己的程序中设计不合理的地方,并来解决问题呢?这就是我们这一节课要给大家讲的内容,就是基于在线Debug的程序调试方法。

调试说明:
1、      如何设置进入调试模式
2、      断点的添加与使用(添加,取消)
3、      变量的查看(全局,局部)
4、      查看外设寄存器值(查看Memory)
5、      单步,进入函数,跳出函数

调试时候主要看的:
1、      变量(variables)
2、      断点(breakpoints)
3、      表达式(Expressions)
4、      存储器(memory)


调试呢叫做debug,在有些开发者的口中呢,他们也经常会称之为在线仿真,我们这里姑且称之为在线调试。方法都是一样的,只是大家的叫法有所差异。

如何进行在线调试呢?Xilinx的SDK开发环境为我们提供了非常便捷的在线调试功能,我们只需要在SDK中点几下按钮,就能够让我们的程序进入到调试状态,在调试状态中,我们可以控制程序一行一行的执行(我们称之为单步执行),在这个程序单步执行的过程中,我们可以去观察每一个变量的值,以及观察程序的分支走向,同时我们还可以设置断点让我们的程序运行到指定的位置停止下来,而在其他情况下全速运行,以节约我们的调试时间,再者,我们可以添加存储器(DDR3)中某一段存储空间在总线上的物理地址,来直接查看其中存储的数据内容。比如我们在做数据采集系统的时候,就可以通过这种方法直接查看FPGA采集并存储到PS侧DDR3中的数据内容,然后我们再通过分析DDR中的数据内容,来进一步分析数据采集系统存在的问题。
甚至,因为各外设控制器在连接到CPU的总线上时各个寄存器也是以存储器的模型呈现的,我们可以采用相同的方法,添加外设控制器的寄存器地址,来查看对应寄存器中的值,通过分析里面的内容,来查看其数据和工作状态。
总之,在线调试这样一个功能在我们的开发中使用的是非常广泛的,就像我们开发fpga的的时候,使用modelsim仿真的方式来分析我们逻辑设计中存在的问题一样。那么来对于我们开发ARM裸机程序来说,在线调试,也是开发中非常重要的环节,大家要想掌握独立的程序设计能力,在线调试的方法和技巧,肯定是要掌握的。


话不多说,我们还是基于上一节课给大家编写的程序,来看一下我们如何进行线调试,基于这样一个简单的工程,带领大家一起来看一下上面说的,如何查看我们的变量,设置我们的断点以及查看我们的内存信息。



进入调试模式

单步运行
进入函数
跳出函数
运行到断点
查看局部变量
查看全局变量(修改变量值)



查看内存内容

#include "xparameters_ps.h"
#include "xil_io.h"
#define DDR_BASEARDDR      XPAR_DDR_MEM_BASEADDR + 0x10000000

int main()
{
    int i;
    int rev;

    for(i=0; i<32; i++)
    {
      Xil_Out32(DDR_BASEARDDR+i*4,i);
    }

    for(i=0; i<32; i++)
    {
      rev = Xil_In32(DDR_BASEARDDR+i*4);
    }

    return 0;
}


全速运行

admin 发表于 2022-6-19 16:52:37


课程完整工程附件如下



课程main.c文件内容附件如下



main.c内容如下


//#include "stdio.h"
//#include "xil_io.h"
//#include "xgpiops_hw.h"
//#include "unistd.h"
//#include "stdint.h"
//
//#include "xil_types.h"
//int main(void)
//{
//                u32 reg_val = 0;
//                u32 Data = 0;
//
//
//                //设置IO方向,bit7的方向为输出
//                reg_val = Xil_In32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_DIRM_OFFSET);
//                Data = reg_val | (1<<7);
//                Xil_Out32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_DIRM_OFFSET, Data);
//
//                //设置输出使能,bit7输出使能
//                reg_val = Xil_In32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_OUTEN_OFFSET);
//                Data = reg_val | (1<<7);
//                Xil_Out32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_OUTEN_OFFSET, Data);
//
//                while(1)
//                {
//                        //设置bit7输出1
//                        Data = ((~(1<<7)) << 16) | (1<<7);
//                        Xil_Out32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_DATA_LSW_OFFSET,Data);
//                        usleep(500000);
//
//                        //设置bit7输出0
//                        Data = ((~(1<<7)) << 16) & (~(1<<7));
//                        Xil_Out32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_DATA_LSW_OFFSET,Data);
//                        usleep(500000);
//                }
//}


#include "xgpiops.h"
#include "unistd.h"

XGpioPs Gpio;
XGpioPs_Config *ConfigPtr;

uint32_t i=0;

int main(void)
{


        ConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
        XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);


        XGpioPs_SetDirectionPin(&Gpio, 7, 1);
        XGpioPs_SetOutputEnablePin(&Gpio, 7, 1);

        /*设置MIO47为输入*/
        XGpioPs_SetDirectionPin(&Gpio, 47, 0);
        XGpioPs_SetOutputEnablePin(&Gpio, 47, 0);

        while(1)
        {
                while(!XGpioPs_ReadPin(&Gpio, 47))
                {
                        //设置bit7输出1
                        XGpioPs_WritePin(&Gpio, 7, 0x1);
                        usleep(500000);

                        //设置bit7输出0
                        XGpioPs_WritePin(&Gpio, 7, 0x0);
                        usleep(500000);
                        i = 3;
                }

                while(i)
                {
                        //设置bit7输出1
                        XGpioPs_WritePin(&Gpio, 7, 0x1);
                        usleep(500000);

                        //设置bit7输出0
                        XGpioPs_WritePin(&Gpio, 7, 0x0);
                        usleep(500000);
                        i = i - 1;
                }

                //设置bit7输出0
                XGpioPs_WritePin(&Gpio, 7, 0x0);
        }



        return 0;
}



//#include "xparameters_ps.h"
//#include "xil_io.h"
//#define DDR_BASEARDDR      XPAR_DDR_MEM_BASEADDR + 0x10000000
//
//int main()
//{
//    int i;
//    int rev;
//
//    for(i=0; i<32; i++)
//    {
//      Xil_Out32(DDR_BASEARDDR+i*4,i);
//    }
//
//    for(i=0; i<32; i++)
//    {
//      rev = Xil_In32(DDR_BASEARDDR+i*4);
//    }
//
//    return 0;
//}


tb一下 发表于 2022-6-19 16:54:03

顶顶顶

admin 发表于 2022-6-19 17:46:15

本楼层作者占位,主要用来统一解答大家学习本节课程过程中遇到的常见问题,后续会再次编辑完善。学习者有疑问的,请在本楼层之后开始提问和讨论。

CJC 发表于 2022-8-16 15:16:46

这里我记录下学习中存在的问题
1、DDR地址在parameters_ps.h中,不在parameters.h中,我找遍了parameters都没有,甚至怀疑我没配置DDR。。。。。
2、在读写DDR测试的时候要注意,读写DDR要把程序放在OCM_RAM中运行,否则很可能会出错,这实例代码很短,且做了偏移处理,所以正常读写,否则跑着跑着会把程序覆盖。
这里说明下怎么在OCM中运行,在Iscript.Id中,

admin 发表于 2022-8-16 15:52:39

CJC 发表于 2022-8-16 15:16
这里我记录下学习中存在的问题
1、DDR地址在parameters_ps.h中,不在parameters.h中,我找遍了parameters都 ...

学习认真,挺好的,要是发现我们课程中有什么缺漏或者错误,也欢迎指出

CJC 发表于 2022-8-17 19:54:19

admin 发表于 2022-8-16 15:52
学习认真,挺好的,要是发现我们课程中有什么缺漏或者错误,也欢迎指出 ...

小梅哥,我觉得新视频录的声音很小,我外放调最大了还是听着小

CJC 发表于 2022-8-18 14:50:01

admin 发表于 2022-8-16 15:52
学习认真,挺好的,要是发现我们课程中有什么缺漏或者错误,也欢迎指出 ...

小梅哥,可以问下预计裸机视频大概录到文档的哪个部分结束呢
页: [1]
查看完整版本: 【zynq课程笔记】【裸机】【第9课 】【裸机程序调试方法】