x210-2023-02-16

1、按26-实验三:用UART显示某指定内存中的数据视频,正常现象应该第一行打印Uart2_Ok!,第二行打印0x1234ABCD,但是实际跑出来的效果却是U和a不见了,而且ABCD也不见了,如下图所示,由于视频所用板子为tini210,而自己手上所用为x210bv4s,因为烧有android时,系统指定了UART2为默认的打印串口,所以为了避免频繁插拔串口线的麻烦,所以并没有按照视频一样使用UART0进行试验而是继续使用UART2。

一开始的思路是可能缓冲区大小不够,先屏蔽掉0x1234ABCD的汇编打印代码看看效果,然后发现第一行能完整打印,如下图所示。

既然能完整显示,那接下来再看看是不是能全部显示到一行,所以这里把打印回车换行的汇编代码给屏蔽掉,发现虽然多显示了AB,但是开头的U和a却不见了,如下图所示,所以这里怀疑到可能是发送FIFO的大小问题,另一个就是视频里展示的汇编代码,它的发送过程并没有等待发送完成的判断,所以造成了后面覆盖前面的现象从而使U和a被顶掉,因此下一步的思路就是从这两个可能原因入手。

 

首先是第一个FIFO大小的问题,虽然查到UART0的FIFO最大能有256byte,而UART2的FIFO最大只有16字节,但是UFCON在初始化的时候并没有对这部分内容进行设置,而只是将UFCON[0]置一了,也就是使能了FIFO,然后再仔细看看UFCON中发送FIFO的大小设置,会发现是关于中断下才有用的,所以这里想要从FIFO大小设置入手变的无计可施,所以接下来就想到先加入等待发送完成的whlie循环判断汇编代码看是否有突破,如下图所示。

 

 

 这个while的循环判断是基于UTRSTAT[2]进行的,在UTXH写入数据的前面进行调用即可,关键的是编写这个while循环需要保存lr的值,而不能直接mov pc,lr,因为lr的值一直被保存在r11中,而r11保存的是uart_asm_init入口地址,一旦执行就会返回到uart_asm_init开始的地方然后继续往下执行,初始化这里一共需要发送Uart2_Ok!\r\n,但只发了一个字节数据U就返回到入口处继续往下,这明显是不应该的,而用于保存lr的寄存器,需要确保不能被当前文件前面的某些地方使用过以保证存储的返回入口地址不被冲掉,所以这里就选用lowlevel_init.S中前面没用过的r10,与此同时,在测试过程中,发现前面UFCON[0]已经置一的初始化内容需要屏蔽掉,否则会无内容打印(因为写while循环的逻辑是参考的前面裸机时串口部分的C测试程序,当时是并没有给UFCON[0]置一的,而后面实际测试发现这个的确会有影响所以要屏蔽),这些都做完会发现第一行Uart2_Ok!能完整打印出来了,而第二行的内容不能打印或者有时候只打印了一个x,如下图所示。

 

 

到了这里卡的是最久的,首先是调试方式的问题,能用于调试的就只有led,但点亮led的子过程(相当于子函数)是在./arch/arm/cpu/armv7/start.S这个文件中,虽然用.global声明到了外部,允许被当前./board/samsung/goni/lowlevel_init.S调用,但是经过前面的调试,由于点亮led的这个子函数也用了mov pc,lr,放到uart_asm_init和display_hex里直接调用的话就相当给自己挖坑,改完再调用的话就相对麻烦(可以改但是需要担心保存lr的寄存器因为没注意而使用了一个已经被使用的,导致lr内容被冲掉就为调试添加了更多不确定性),所以决定在uart_asm_init和display_hex内部直接再用另一个led(内部点亮的这个led需要减少跳转的干扰因此直接使用最原始的ldr、bic、str操作而不要再封装成子过程),而在外部(uart_asm_init和display_hex前后和中间的位置)就直接调用原来的这个led,接下来就是调试过程,由于没有别的办法了,只能通过这两个led一内一外去包夹缩小来定位问题语句,由于前面调试的结果已经得知,在第一行打印完就没有继续打印了,所以一个led需要放在uart_asm_init内部Uart2_OK!\r\n的\r、\n这里前后和中间分别测试是否能亮,然后再在外边的uart_asm_init和display_hex之间放一个led,后面测试发现,uart_asm_init和display_hex之间的led不亮,而uart_asm_init内部Uart2_OK!\r\n的\n后面的led还能亮,说明在离开uart_asm_init到进入display_hex之前出了问题,这个中间只有两条语句,一个是标号200:mov pc,lr,另一条是给r0赋值0x1234abcd,很明显,问题应该在标号200:mov pc,lr这条语句,起初定位到这里了但是没有思路了,后来网上看到一句话,在子过程中调用了子过程,需要将lr保存到栈sp中(r13),刚好在lowlevel_init.S前面还没使用过r13,然后再代入测试就可以了,如下图所示。

 

 

 

 

 

 

 

posted @ 2023-02-17 15:33  migui  阅读(26)  评论(0)    收藏  举报