一、起因
在ubuntu上搭建好开发环境后,编译了官方的例程,但开发板的硬件与官方开发板的差异还是很大的,虽然编译了例程,但几乎没有可以运行运行的例程,所以,就重新编译了官方提供的例程。
文件是RP2040-LCD-1.28.zip,在ubuntu下进行编译。
但是编译好的文件,烧写到开发板上,运行到Paint_DrawImage后,就不再运行,也无法显示while中的六轴数据。
会卡在如下界面:
重新下载官方文件中已经编译好的文件,就可以正常运行,自己编译的就不行。可以确定的是代码没有修改过。
gcc的版本是9.2.1
cmake的版本是3.16.3
猜可能是编译器的问题,知道官方使用的编译环境是哪些版本的。所以,按官方的方法,又在windows下搭建了环境。
重新编译后,一样的结果。
windows的编译时,打开的命令行要是Visual Studio 2019目录下的,运行的命令为:
cd E:\workspace_RP2040\pico-sdk-master
mkdir build
cd build
cmake -G "NMake Makefiles" ..
nmake
二、查找
通过逐行的排查,发现是Paint_DrawNum函数导致的,如果在while中调用了Paint_DrawNum函数,程序将会卡住。
找到该函数的源码如下,就把数字转换成字符串并显示。
#define ARRAY_LEN 255
void Paint_DrawNum(UWORD Xpoint, UWORD Ypoint, double Nummber,
sFONT *Font, UWORD Digit, UWORD Color_Foreground, UWORD Color_Background)
{
char Str[ARRAY_LEN];
sprintf(Str, "%.*lf", Digit + 1, Nummber);
char *pStr = (char *)malloc((strlen(Str)) * sizeof(char));
memcpy(pStr, Str, (strlen(Str) - 1));
*(pStr + strlen(Str) - 1) = '\0';
if (Digit == 0)
*(pStr + strlen(Str) - 2) = '\0';
// show
Paint_DrawString_EN(Xpoint, Ypoint, (const char *)pStr, Font, Color_Foreground, Color_Background);
free(pStr);
pStr = NULL;
}
由于在程序开始时,在第一屏的显示上,也调用了这个函数,显示了一个flaot的小数,是可以正常的,说明函数本身应该是没有问题的。
但到while中却显示不正常,确实有一些不解。
唯一不同的,就是字号的不同。初始化进的字号是20,while中的字号是16.所以,把while中的字号修改成20再测试时,也是一样的结果。
三、解决
从Paint_DrawNum的源码上看,逻辑应该是没有问题的,在linux也单独测试了这个函数,也是可以正常输出的,那么问题就可能出在交叉编译时,编译器对这个函数的处理上。
如下,是测试进的程序
整个函数上看,唯一可能有问题的就是malloc与free这些涉及到内存处理的函数了,所以,把这个函数修改成如下
#define ARRAY_LEN 255
void Paint_DrawNum(UWORD Xpoint, UWORD Ypoint, double Nummber,
sFONT *Font, UWORD Digit, UWORD Color_Foreground, UWORD Color_Background)
{
#if 1
char Str[ARRAY_LEN];
sprintf(Str, "%.*lf", Digit, Nummber);
// char *pStr = (char *)malloc((strlen(Str)) * sizeof(char));
// memcpy(pStr, Str, (strlen(Str) - 1));
// *(pStr + strlen(Str) - 1) = '\0';
// if (Digit == 0)
// *(pStr + strlen(Str) - 2) = '\0';
// show
Paint_DrawString_EN(Xpoint, Ypoint, (const char *)Str, Font, Color_Foreground, Color_Background);
// free(pStr);
// pStr = NULL;
#endif
}
再烧写到开发板上,程序顺利运行。
本帖最后由 jinyi7016 于 2022-11-25 14:04 编辑
引用: nmg 发表于 2022-11-25 14:35 微雪官方给的例程,和开发板不配套?
可能是SDK版本或是编译器版本不同的原因,毕竟官方提供的可烧写文件是正常的。
这个问题是因为在while或者for循环中,编译器自作主张认为你是重复做无意义的事情,所以进行了优化。你会发现都是在while或者for中有问题,就是因为编译器聪明过头,认为你在做无意义重复的事,虽然实际上我们的重复是有意义的。
将相应的变量加上volatile修饰就可以了。
或者取消编译器优化,优化等级设置为-O0,这样程序会很大,效率低,不是我们期望的,一般我们还是会默认开编译器优化的。
楼上的大佬对这个理解到位呀,看后感触非凡。微雪的产品,也很给力。