Tiny4412裸机开发过程(四) --- 点亮LED灯和下载裸机程序

        本节算是切入正题,正式开始编写我们裸机程序。那么在编写裸机程序时与我们写单片机程序如STM32有什么不同?其实在编写时的步骤与单片机一般无二,基本步骤一般是查看硬件原理图,查看芯片手册,编写程序,下载程序。下面我们也按这个步骤来。

查看硬件原理图:



        通过查看原理图我们知道了两个信息:四个LED灯连接在GPM4_0-GPM4_3的IO口上,且是低电平有效(即给低电平点亮灯)。知道了硬件连线,接下来就要知道如何操控IO口输出低电平,那么就要查看芯片手册了。


查看芯片手册:

        datasheet长达2800多页,我们直接搜索GPM4CON查看该管脚的控制寄存器。和STM32类似,需要通过寄存器来配置管脚为 ”输出模式“ 。怎么配置呢?通过下图我们发现管理的GPM4引脚是一个32的寄存器 ,并且每四个位决定决定了管脚的模式 。该寄存器的基地址为:0x11000000 偏移地址为:0x02e0 得出该寄存器的地址为:0x1100 02e0

             


        这里假设要给GPM4_1设置输出模式,那么就应该把该位设置为 0001对应图中的0x1。接着如果要让该IO口输出高低电平就要接着设置他的数据寄存器看下图:


        数据寄存器是8位的寄存器,刚好一位控制一个管脚。给相应位写1或写0,就可输出高低电平。同样该寄存器也有相应地址为:0X1100 02e4

        

编写程序:

        方便起见,我直接在ubuntu内写程序了,也可在windows下编写,完后再传入ubuntu编译。以下是流水灯程序,我都有注释,自己好好推敲一下,不难理解。

        

#define gpiobase        0x11000000
#define GPM4CON         (*(volatile unsigned long *)(gpiobase + 0x02E0))  //控制寄存器地址 基地址+偏移值地址
#define GPM4DAT         (*(volatile unsigned long *)(gpiobase + 0x02E4))  //数据寄存器地址 

void led_test(void);

int test(void)          
{
        led_test();
        return 0;
}

void delay(int num)    //自己写的延迟函数 单位毫秒
{
        int i,j;
        for(i=0;i<2100;i++)
        for(j=0;j<num;j++);
}
void led_test(void)
{
        int i=0;

        GPM4CON  &= ~0xffff;   //清位   把前16位先清零  
        GPM4CON  |= 0x1111;    //置位   把前16位 置1 ,让其配置成输出模式 
        GPM4DAT  |= 0xf;        //把前4位置1 即开机上电首先灭灯

        for(i=0;i<=4;i++)
        {
                GPM4DAT&=(0xf<<i);
                delay(1500);
        }
        GPM4DAT  |= 0xf;

        for(i=0;i<=4;i++)
        {
                GPM4DAT&=(0xf>>i);
                delay(1500);
        }

}

        仔细观察发现好像跟我们的STM32单片机程序还是有点区别的 1.没有了mian函数而是用test()函数,其实test也可以写成main,它只是个函数名罢了。那它怎么从找到程序的入口地址的,在我看来在Makefile里面有”arm-linux-ld  -Ttext=0x70003000  test.o  -o test“这句话就是关键,他把程序的代码段放到了0x700030000的地址上,所以等会下载程序时会把程序放到这里作为程序的入口地址。2.本函数没有调用头文件,所有的操作都是操控寄存器。程序编写完后,接着开始写Makefile文件,代码如下:     

default:
        arm-linux-gcc -c test.c  -o test.o
        arm-linux-ld  -Ttext=0x70003000  test.o  -o test
        arm-linux-objcopy  -O binary   test  test.bin
clean:
        rm -f test.o  test  test.bin   *~

        为什么,我们要写Makefile文件?他用来做什么?其实观察这个文件,不难发现他是一条条的指令,也就说本我们可以不写makefile文件,直接一句一句的执行命令也不是不行,但是如果每写一个程序都要一条条执行指令j不免太过于麻烦,于是我们可以将编译的选项和命令都写在这个文件里,方便管理的同时,也方便修改。有兴趣的朋友可以自己去了解Makefile文件更强大之处。

        紧接着,Makefile文件搞定后直接在当前目录 make ,就生成了test.bin的二进制文件,这个文件就是我们等会要下载进去的文件


        之后就是下载程序了,下载程序的方式多种多样,这里我是用dnw来烧写程序。安装dnw步骤:首先我还是将压缩包放到root目录下,解压完后出现如下文件夹。


        

    我们直接在dnw-linux目录下make会出现错误,详情可以参考这篇博文

https://blog.csdn.net/qq_33160790/article/details/77677173,但要注意不能直接复制粘贴哦,像下边这样就不正确的


        正确的做法是复制粘贴后,在箭头那边将空的部分删去,再按下一个tab键(不要使用空格),如下图才是正确的:




        最后成功生成secbulk.ko的驱动模块文件后,就可用 insmod 命令加载这个模块 (这方面是linux驱动方面的知识了)。

        insmod secbulk.ko   

        最后回到 dnw-linux根目录执行,成功后如下图。

        make install


    这个时候dnw就在ubuntu下安装好了

    在串口终端上执行命令,表示启动dnw把程序下载到70003000的地址上,这里不能随意更改下载地址,如果要更改的话,就需要改对应的Makefile文件。

    dnw 70003000


        可以看到uboot这边已经准备好了,正在等待下载。

        这个时候dnw如果连接到windos下,需要我们手动连接到ubuntu下,像下面那样点击连接,完后查询下驱动是否已经正确挂载。

        lsusb


        再查询下是否有这个模块

        ls /dev/ -l



        最后在ubuntu下执行命令

        dnw test.bin



        完后查看串口终端提示下载成功,在这过程中遇到过由于dnw的问题如果下载不成功,那么可能就需要多次下载。如下图那样就表示成功了。


        终于到这一步了,开始验证我们的程序,执行如下指令到相应地址开始运行我们的程序。

        go 70003000

        提示正在运行。。。


           大功告成!运行效果如图


    附上程序和dnw工具:

    链接:https://pan.baidu.com/s/1h6lKjqpTVTMjlX7cnthlQQ 密码:depa

猜你喜欢

转载自blog.csdn.net/qq_35281599/article/details/80360624
今日推荐