先Po个图,尽量坚持调试完开源(取决于事多不多 )
Randolph 发布的最佳帖子
-
【XR806开发板试用】棋子分拣机
最近沉迷于看《棋魂》,突发奇想做个棋子分拣机器。刚好涉及到的材料与之前写的XR806例程能差不多对应上,就差一个外壳,于是圣诞节就宅在实验室画了草图,趁着月黑风高偷偷用学校的CNC切了一个模型,基于XR806开发板和openHarmony实现了分拣棋子的功能。
先放个效果视频:
时间仓促,做工不是很精细,功能上也有待继续完善,比如说显示计数界面和联网功能云云····后面会慢慢填坑 。 -
在哪吒sdk中新建D1s方案的方法
1、在device/config/chips/d1/configs下新建文件夹命名为d1-d1sevb,将同文件夹下的nezha的内容复制过去,并按照参考文章修改文件内容。
链接文本2、package\allwinner\alsa-conf-aw\files\d1下新建文件夹d1-d1sevb,同样将同文件下nezha中的内容复制过去。
3、在target/allwinner下新建文件夹,命名为d1sevb,并将同文件夹下d1-nezha中的所有内容复制到d1sevb中,并修改文件名,及文件中的内容,使其指向d1sevb项目。
PRODUCT_NAME := d1_d1sevb PRODUCT_DEVICE := d1-d1sevb
makefile中修改:
BOARD:=d1-d1sevb BOARDNAME:=d1-d1sevb
TinaProducts.mk中修改:
PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/d1_d1sevb.mk
vendorsetup.sh中修改:
add_lunch_combo d1_d1sevb-tina
4、根目录执行
souce build/environment setup
lunch后可以看到有新增的编译target
选择d1sevb,编译生成镜像,pack打包后用PhoenixSuit烧录。
成功进入系统。
-
【XR806开发板试用】跑个步进电机
从垃圾堆里翻出来个电机,今天就玩它好了,对于电机的理解已经全部还给了大学老师,所以打算先研究一番:
百度了一下,这个东西学名叫作四相五线步进电机,电机就是这个圆陀陀,板子是他的驱动器。板载芯片是ULN2003,TI出品。查了一下技术文档,就是一个集成的达令顿管放大器。
很早以前就了解过:步进电机是吃脉冲信号工作,转化信号成相应的角位移和线位移。输入一个脉冲信号,转子就转动一个角度或前进一步,其输出的角位移或线位移与输入的脉冲数成正比,转速与脉冲频率成正比。因此,步进电动机又称脉冲电动机。
步进电机相对于其它控制用途电机的最大区别是,它接收数字控制信号(电脉冲信号)并转化成与之相对应的角位移或直线位移。也就是说,它本身就可以把信号转化成运动。而且它可开环位置控制,输入一个脉冲信号就得到一个规定的位置增量,与传统的直流控制系统相比,其成本明显减低,几乎不必进行系统调整。所以他给我们带来了很大的方便。要是想要他执行起来也很简单,只要控制脉冲的数量、频率和电机绕组的相序,即可获得所需的转角、速度和方向。
从具体的硬件来看,我这里需要接六条线才能让这个电机跑起来,电源端口就不说了,IN1~IN4这四个通道口要怎么输入信号才是问题所在。
如上就是内部原理图,右侧四个开关其实就是我们的四个信号端口。右侧ABCD为定子,上面绕有线圈,为四相,与之相对应的对面四个定子上面也有线圈,相对应的两个定子之间线圈是相互连接形成一个绕组。
下面来分析一种运行模式,单四拍运行:假如说现在我闭合0对着的那个开关,则由高中学过的电能生磁原理,0对应的线圈就会产生磁力,同时他的下端,也就是对应的B线圈,也就一起导通了。接下来B断开,C导通产生磁力,1和C(这里指的是右上角那个端)就会因为两者间夹角最小而互相吸引靠近,吸引过去后C断开,D通电,继续把离他最近的2吸引过去,如此一来类推下去就形成了一个逆时针旋转的过程。
上述过程直到0被吸引到A相时,就是一个周期的完成,旋转角度为360/8=45度。
还有其他控制方法,如双拍工作、单双拍工作等等,可以根据需求调节精度速度等等···决定先放一边,适当做点容易让人有成就感的事情:用代码实现这个过程,把舵机跑起来。
了解了原理就用最简单的方法去实现好了。主要代码如下:
IoTGpioSetOutputVal(12,0); IoTGpioSetOutputVal(13,0); IoTGpioSetOutputVal(19,1); IoTGpioSetOutputVal(20,1); OS_MSleep(2); IoTGpioSetOutputVal(12,1); IoTGpioSetOutputVal(13,0); IoTGpioSetOutputVal(19,0); IoTGpioSetOutputVal(20,1); OS_MSleep(2); IoTGpioSetOutputVal(12,1); IoTGpioSetOutputVal(13,1); IoTGpioSetOutputVal(19,0); IoTGpioSetOutputVal(20,0); OS_MSleep(2); IoTGpioSetOutputVal(12,0); IoTGpioSetOutputVal(13,1); IoTGpioSetOutputVal(19,1); IoTGpioSetOutputVal(20,0); OS_MSleep(2);
像前面几篇一样,烧录程序,将对应IO连接上驱动板后,通上电,电机就正常工作了。
当然光转起来有些过于简单了,所以打算加一些可控元素进去,也方便后面做各种开发。于是又从垃圾堆里翻到了这个:
用翻出来的示波器研究了一下(没有万用表555),可以理解为由上下、左右两个方向的滑动变阻器和一个按键组成,总共三个信号输出口。保持在中间位置的时候测得是2.5v,移动向两边就是0跟5v,按下就是按钮。
既然是输出模拟信号最合理就是用ADC检测,无奈鸿蒙1.x.x的版本貌似都还没适配好806的接口,hal库的代码也找不到说明文档,用hal库尝试配置了一下ADC一直没成功,只能放到后面解决了。。。
所以最终决定还是用GPIO接口去读电平高低,具体代码如下:
#Create by Randolph. import("//device/xradio/xr806/liteos_m/config.gni") static_library("app_Stepper") { configs = [] sources = ["main.c",] cflags = board_cflags include_dirs = board_include_dirs include_dirs += [ "//kernel/liteos_m/kernel/arch/include", "//base/iot_hardware/peripheral/interfaces/kits", "//device/xradio/xr806/xr_skylark/src/rom/rom_bin/src/driver", ] }
main.c
//Create by Randolph #include <stdio.h> #include "kernel/os/os.h" #include "ohos_init.h" #include "iot_gpio.h" static OS_Thread_t g_main_thread; unsigned char mode; static void gpio_init(void) { IoTGpioInit(11); IoTGpioInit(12); IoTGpioInit(13); IoTGpioInit(19); IoTGpioInit(20); IotGpioDir dir; IoTGpioSetDir(11, IOT_GPIO_DIR_IN); IoTGpioGetDir(11, &dir); IoTGpioSetDir(12, IOT_GPIO_DIR_OUT); IoTGpioSetDir(13, IOT_GPIO_DIR_OUT); IoTGpioSetDir(19, IOT_GPIO_DIR_OUT); IoTGpioSetDir(20, IOT_GPIO_DIR_OUT); } static void Servo_mode(unsigned char mode) { if (mode == 1) { IoTGpioSetOutputVal(12,0); IoTGpioSetOutputVal(13,0); IoTGpioSetOutputVal(19,1); IoTGpioSetOutputVal(20,1); OS_MSleep(2); IoTGpioSetOutputVal(12,1); IoTGpioSetOutputVal(13,0); IoTGpioSetOutputVal(19,0); IoTGpioSetOutputVal(20,1); OS_MSleep(2); IoTGpioSetOutputVal(12,1); IoTGpioSetOutputVal(13,1); IoTGpioSetOutputVal(19,0); IoTGpioSetOutputVal(20,0); OS_MSleep(2); IoTGpioSetOutputVal(12,0); IoTGpioSetOutputVal(13,1); IoTGpioSetOutputVal(19,1); IoTGpioSetOutputVal(20,0); OS_MSleep(2); } else if (mode == 0) { IoTGpioSetOutputVal(12,0); IoTGpioSetOutputVal(13,1); IoTGpioSetOutputVal(19,1); IoTGpioSetOutputVal(20,0); OS_MSleep(2); IoTGpioSetOutputVal(12,1); IoTGpioSetOutputVal(13,1); IoTGpioSetOutputVal(19,0); IoTGpioSetOutputVal(20,0); OS_MSleep(2); IoTGpioSetOutputVal(12,1); IoTGpioSetOutputVal(13,0); IoTGpioSetOutputVal(19,0); IoTGpioSetOutputVal(20,1); OS_MSleep(2); IoTGpioSetOutputVal(12,0); IoTGpioSetOutputVal(13,0); IoTGpioSetOutputVal(19,1); IoTGpioSetOutputVal(20,1); OS_MSleep(2); } } static void MainThread(void *arg) { while (1) { IoTGpioGetInputVal(11,&mode); Servo_mode(mode); } } void Stepper_TestMain(void) { printf("Test Start\n"); gpio_init(); if (OS_ThreadCreate(&g_main_thread,"MainThread",MainThread, NULL, OS_THREAD_PRIO_APP, 4096) != OS_OK) { printf("[ERR] Create HelloWorld_Task Failed\n"); } } SYS_RUN(Stepper_TestMain);
看看效果:
至于为什么要顶个风扇叶呢,一方面是方便观察转动,另一方面也算是致敬一张大部分程序员应该都见过的图:
ok,又水了一贴,今天也是平安夜,祝各位圣诞快乐!
也挖个坑:下周会整合一下前面的内容做个小作品放出来。Merry Christmas!
-
【跑个算法】之模拟退火算法在D1的执行
前言:之前有做过一个VLSI布局布线相关的课题,学了一点关于模拟退火算法的毛皮,今天来跑个demo复(shui)习(tie)一下 。
Simulated annealing这种算法的出发点是基于物理中固体物质的退火过程与一般组合优化问题之间的相似性。模拟退火算法是一种通用的优化算法,其物理退火过程由以下三部分组成:
(1)加温过程
(2)等温过程
(3)冷却过程
其中加温过程对应算法设定的初始温度,等温过程对应算法的Metropolis(一种采样算法)抽样过程,冷却过程对应控制参数的下降。这里能量的变化就是目标函数,要得到的最优解就是能量最低状态。Metropolis准则是SA算法收敛于全局最优解的关键所在,Metropolis准则以一定的概率接受恶化解。
总的来说就一句话:相比于类似爬山算法这种贪心算法,SA可以跳出局部最优解。
理解的大概原理后,就来看看代码。
/* * 使用模拟退火算法(SA)求解TSP问题(以中国TSP问题为例) * 参考自《Matlab 智能算法30个案例分析》 * 模拟退火的原理这里略去,可以参考上书或者相关论文 * update: 16/12/11 * author:lyrichu * email:919987476@qq.com */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> #include<math.h> #define T0 50000.0 // 初始温度 #define T_end (1e-8) #define q 0.98 // 退火系数 #define L 1000 // 每个温度时的迭代次数,即链长 #define N 31 // 城市数量 int city_list[N]; // 用于存放一个解 double city_pos[N][2] = {{1304,2312},{3639,1315},{4177,2244},{3712,1399},{3488,1535},{3326,1556},{3238,1229},{4196,1004},{4312,790}, {4386,570},{3007,1970},{2562,1756},{2788,1491},{2381,1676},{1332,695},{3715,1678},{3918,2179},{4061,2370},{3780,2212},{3676,2578},{4029,2838}, {4263,2931},{3429,1908},{3507,2367},{3394,2643},{3439,3201},{2935,3240},{3140,3550},{2545,2357},{2778,2826},{2370,2975}}; // 中国31个城市坐标 //函数声明 double distance(double *,double *); // 计算两个城市距离 double path_len(int *); // 计算路径长度 void init(); //初始化函数 void create_new(); // 产生新解 // 距离函数 double distance(double * city1,double * city2) { double x1 = *city1; double y1 = *(city1+1); double x2 = *(city2); double y2 = *(city2+1); double dis = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); return dis; } // 计算路径长度 double path_len(int * arr) { double path = 0; // 初始化路径长度 int index = *arr; // 定位到第一个数字(城市序号) for(int i=0;i<N-1;i++) { int index1 = *(arr+i); int index2 = *(arr+i+1); double dis = distance(city_pos[index1-1],city_pos[index2-1]); path += dis; } int last_index = *(arr+N-1); // 最后一个城市序号 int first_index = *arr; // 第一个城市序号 double last_dis = distance(city_pos[last_index-1],city_pos[first_index-1]); path = path + last_dis; return path; // 返回总的路径长度 } // 初始化函数 void init() { for(int i=0;i<N;i++) city_list[i] = i+1; // 初始化一个解 } // 产生一个新解 // 此处采用随机交叉两个位置的方式产生新的解 void create_new() { double r1 = ((double)rand())/(RAND_MAX+1.0); double r2 = ((double)rand())/(RAND_MAX+1.0); int pos1 = (int)(N*r1); //第一个交叉点的位置 int pos2 = (int)(N*r2); int temp = city_list[pos1]; city_list[pos1] = city_list[pos2]; city_list[pos2] = temp; // 交换两个点 } // 主函数 int main(void) { srand((unsigned)time(NULL)); //初始化随机数种子 time_t start,finish; start = clock(); // 程序运行开始计时 double T; int count = 0; // 记录降温次数 T = T0; //初始温度 init(); //初始化一个解 int city_list_copy[N]; // 用于保存原始解 double f1,f2,df; //f1为初始解目标函数值,f2为新解目标函数值,df为二者差值 double r; // 0-1之间的随机数,用来决定是否接受新解 while(T > T_end) // 当温度低于结束温度时,退火结束 { for(int i=0;i<L;i++) { memcpy(city_list_copy,city_list,N*sizeof(int)); // 复制数组 create_new(); // 产生新解 f1 = path_len(city_list_copy); f2 = path_len(city_list); df = f2 - f1; // 以下是Metropolis准则 if(df >= 0) { r = ((double)rand())/(RAND_MAX); if(exp(-df/T) <= r) // 保留原来的解 { memcpy(city_list,city_list_copy,N*sizeof(int)); } } } T *= q; // 降温 count++; } finish = clock(); // 退火过程结束 double duration = ((double)(finish-start))/CLOCKS_PER_SEC; // 计算时间 printf("采用模拟退火算法,初始温度T0=%.2f,降温系数q=%.2f,每个温度迭代%d次,共降温%d次,得到的TSP最优路径为:\n",T0,q,L,count); for(int i=0;i<N-1;i++) // 输出最优路径 { printf("%d--->",city_list[i]); } printf("%d\n",city_list[N-1]); double len = path_len(city_list); // 最优路径长度 printf("最优路径长度为:%lf\n",len); printf("程序运行耗时:%lf秒.\n",duration); return 0; }
这是网上找到一个商旅问题的SA解决方法例子,稍加修改后交叉编译一下到开发板上执行。
保存为test.c文件到哪吒SDK下后,执行:
$/prebuilt/gcc/linux-x86/riscv/toolchain-thead-glibc/riscv64-glibc-gcc-thead_20200702/bin/riscv64-unknown-linux-gnu-gcc -o test -lm test.c
用adb传送生成的可执行文件到开发板上,执行:
$chmod +x test $./test
即可,下面看看执行效果:
D1s麻雀:
root@TinaLinux:/# ./test 采用模拟退火算法,初始温度T0=50000.00,降温系数q=0.98,每个温度迭代1000次,共降温1448次,得到的TSP最优路径为: 22--->18--->3--->17--->19--->16--->4--->2--->8--->9--->10--->7--->6--->5--->23--->11--->13--->12--->14--->15--->1--->29--->31--->30--->27--->28--->26--->25--->24--->20--->21 最优路径长度为:15385.425778 程序运行耗时:17.578781秒. root@TinaLinux:/# ./test 采用模拟退火算法,初始温度T0=50000.00,降温系数q=0.98,每个温度迭代1000次,共降温1448次,得到的TSP最优路径为: 5--->6--->7--->10--->9--->8--->2--->4--->16--->19--->17--->3--->18--->22--->21--->20--->24--->25--->26--->28--->27--->30--->31--->29--->1--->15--->14--->12--->13--->11--->23 最优路径长度为:15385.425778 程序运行耗时:17.594397秒. root@TinaLinux:/# ./test 采用模拟退火算法,初始温度T0=50000.00,降温系数q=0.98,每个温度迭代1000次,共降温1448次,得到的TSP最优路径为: 14--->15--->1--->29--->31--->30--->27--->28--->26--->25--->23--->4--->8--->9--->10--->2--->7--->6--->5--->16--->19--->17--->3--->18--->22--->21--->20--->24--->11--->13--->12 最优路径长度为:16245.867392 程序运行耗时:17.584901秒.
D1-H哪吒:
root@TinaLinux:/# ./test 采用模拟退火算法,初始温度T0=50000.00,降温系数q=0.98,每个温度迭代1000次,共降温1448次,得到的TSP最优路径为: 4--->8--->9--->10--->2--->7--->6--->5--->23--->11--->13--->12--->14--->15--->1--->29--->31--->30--->27--->28--->26--->25--->24--->20--->21--->22--->18--->3--->17--->19--->16 最优路径长度为:15402.341890 程序运行耗时:17.511801秒. root@TinaLinux:/# ./test 采用模拟退火算法,初始温度T0=50000.00,降温系数q=0.98,每个温度迭代1000次,共降温1448次,得到的TSP最优路径为: 15--->1--->29--->31--->30--->27--->28--->26--->22--->21--->20--->25--->24--->19--->17--->18--->3--->16--->4--->2--->8--->9--->10--->7--->6--->5--->23--->11--->13--->12--->14 最优路径长度为:15593.696331 程序运行耗时:17.513332秒. root@TinaLinux:/# ./test 采用模拟退火算法,初始温度T0=50000.00,降温系数q=0.98,每个温度迭代1000次,共降温1448次,得到的TSP最优路径为: 12--->14--->15--->1--->31--->30--->25--->20--->21--->22--->18--->3--->17--->19--->24--->26--->28--->27--->29--->11--->23--->16--->4--->8--->9--->10--->2--->5--->6--->7--->13 最优路径长度为:16155.269857 程序运行耗时:17.514657秒.
可以看到时间都在17s左右,哪吒稍快一点点。不过可惜手里没有类似的开发板对比,只能拿一个猎奇一点的来对比:
H3夸克(稚晖君那个小电脑)
由于使用的是H3,就直接用GCC编译即可生成执行文件。
发现屏幕没有中字模哈哈,串口运行看看:pi@Quark-N:~/WorkSpace/SA_Algorithm$ ./test 采用模拟退火算法,初始温度T0=50000.00,降温系数q=0.98,每个温度迭代1000次,共降温1448次,得到的TSP最优路径为: 27--->30--->31--->1--->15--->14--->13--->12--->29--->11--->23--->5--->6--->7--->10--->9--->8--->2--->4--->16--->19--->17--->3--->18--->22--->21--->20--->24--->25--->26--->28 最优路径长度为:15683.072504 程序运行耗时:39.690700秒. pi@Quark-N:~/WorkSpace/SA_Algorithm$ ./test 采用模拟退火算法,初始温度T0=50000.00,降温系数q=0.98,每个温度迭代1000次,共降温1448次,得到的TSP最优路径为: 27--->31--->30--->25--->20--->24--->23--->5--->6--->11--->29--->1--->15--->14--->12--->13--->7--->10--->9--->8--->2--->4--->16--->19--->17--->3--->18--->22--->21--->26--->28 最优路径长度为:16072.436112 程序运行耗时:39.947321秒. pi@Quark-N:~/WorkSpace/SA_Algorithm$ ./test 采用模拟退火算法,初始温度T0=50000.00,降温系数q=0.98,每个温度迭代1000次,共降温1448次,得到的TSP最优路径为: 19--->16--->4--->8--->9--->10--->2--->7--->6--->5--->23--->24--->20--->25--->29--->11--->13--->12--->14--->15--->1--->31--->30--->27--->28--->26--->21--->22--->18--->3--->17 最优路径长度为:15996.839897 程序运行耗时:39.952181秒.
将近40秒。而且不出所料,执行完后非常烫手(毕竟板子尺寸摆在那里)。前两者相比起来就较为风轻云淡。当然了这之间其实也没什么可比性,毕竟夸克还同时点着个屏幕,玩起来纯属娱乐哈哈,如果有大佬有兴趣也可以尝试优化一下,我还是希望起个抛砖引玉的作用 。
至于每次的结果为什么都不一样,简单按网上内容解释一下:SA算法本身是一种随机算法,转移向更差的解不是必然,而是概率性的,也就是说每次执行算法时,执行过程转移到的解可能都是完全不一样的。至于旅行商(Traveling Salesman Problem, TSP) 问题,本身属于NP-hard问题,找不到存在多项式时间复杂度的解。
如果要求精确的解,目前可行的方法有枚举、分支限界、动态规划等,但这些方法适用的数据范围都很小,一旦数据规模变大,它们都将无能为力。所以目前广泛使用的大都是一些随机算法,比如蚁群、遗传等,模拟退火就是其中的一种,这些算法的一大特点就是通过随机去逼近最优解,但也有可能得到错解。
最后贴上一个经典视频:
ok,今天的帖就水到这里。
-
分享一款二次元PCB设计
分享一款二次元PCB设计,重新点燃了我的二次元之魂。
这个是我在翻CPU仿真相关的书籍时找到的一款配套开发板,这款CPU基板AZPR EvBoard(别名:基板少女) 由一个叫做" 从头开始做 CPU "的社团制作,搭载了XILINX公司的FPGA。可惜书是日文没有汉化。JLC打了几片看看:
可惜如今已经买不起赛灵思的片子了 -
回复: 【XR806开发板试用】棋子分拣机
技术原理
关于技术实现,用到的材料主要有XR806开发板、两个9g的舵机,以及一个红外光传感器。
工作机制非常简单,如图所示:
上电后舵机复位到初始状态,任何开始工作,由一号舵机把待分类的棋子推移到检测区域,由红外传感器判断棋子的颜色,白色返回值为1,黑色则为0。
硬件模型制作
这一部分看似工作量大,但其实是参考了网上一些开源的例程,只不过加以了尺寸改动。
实现方法可以用3d打印或者激光切割亚克力,我选择了后者因为时间相对简短。使用的建模软件为Solidworks2019,亚克力板厚度后3mm,画好零件后,搭建好装配体确认尺寸无误后转为dxf格式即可用CNC机床切割。(我是用了学校的CNC,网上切也很便宜哈)
电路部分
使用的开发板为XR806,一款iot产品开发板,他最大的特点就是适配的轻鸿蒙,使用起来能有不错的体验。
需要驱动的设备就是两个舵机及一个红外传感器。
舵机就是一种位置伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统。其工作原理是:控制信号由接收机的通道进入信号调制芯片,获得直流偏置电压。它内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号,将获得的直流偏置电压与电位器的电压比较,获得电压差输出。最后,电压差的正负输出到电机驱动芯片决定电机的正反转。当电机转速一定时,通过级联减速齿轮带动电位器旋转,使得电压差为0,电机停止转动。
以180度角度伺服为例,那么对应的控制关系是这样的:
0.5ms--------------0度;
1.0ms------------45度;
1.5ms------------90度;
2.0ms-----------135度;
2.5ms-----------180度;
拆开看看:
减速齿轮
驱动电路
因为片子上的字眼实在太小,令人“望眼欲穿”,本来还想查查有没有技术文档研究一下,只能放弃先了。刚好鸿蒙也适配了pwm的接口驱动xr806,所以我们只要修改freq频率和duty占空比两个选项如下即可。
IoTPwmStart(PWM_OUTPUT_CH0,8,50);
关于其他基础操作姿势可以参考我之前的一篇呼吸灯的demo帖子。还有一点值得一提的是关于这种舵机的输入信号口我是用806上的接口直接驱动的,并没有再拉高,内部是否需要或者有没有额外的驱动由于没有舵机内部电路的原理图也暂时无从得知,但总感觉在调节duty占空这一参数时舵机时而会不听使唤(占空比调制不准确),希望有大佬指点。
红外传感器原理则相对简单,一个红外发射管和一个红外接收管。模块通电后红外发射管向前方不断发射一定频率的红外线,
通过板载了一个电压比较器LM393
比较输出和输入的信号做出相应反馈,体现到我手里这块小板子上就是接收到红外信号为1,没有接收到(遇到黑色物体)则为0。所以读取判断值的代码相对简单:
IoTGpioGetInputVal(13,&mode);
整体代码部分
openHarmony用的是gn和ninja编译,由很多种上手学习方式,如果说gn对标的是gcc脚本构建生成器,ninja就对应的是makefile构建系统文档了。
#Create by Randolph. import("//device/xradio/xr806/liteos_m/config.gni") static_library("app_GO") { configs = [] sources = ["main.c",] cflags = board_cflags include_dirs = board_include_dirs include_dirs += [ "//kernel/liteos_m/kernel/arch/include", "//base/iot_hardware/peripheral/interfaces/kits", "//device/xradio/xr806/xr_skylark/src/rom/rom_bin/src/driver", ] }
main.c
//Create by Randolph #include "kernel/os/os.h" #include "ohos_init.h" #include "iot_pwm.h" #include "driver/chip/hal_pwm.h" #define PWM_OUTPUT_CH0 PWM_GROUP0_CH0 //front #define PWM_OUTPUT_CH1 PWM_GROUP0_CH1 //back static OS_Thread_t g_main_thread; unsigned char mode; static void Servo_init(void) { IoTPwmInit(GPIO_PORT_A); IoTGpioInit(13); } static void Servo_reset(void) { printf("0/n"); IoTPwmStart(PWM_OUTPUT_CH0,8,50); OS_MSleep(500); printf("1/n"); IoTPwmStart(PWM_OUTPUT_CH1,8,50); OS_MSleep(500); } static void Servo_start(void) { printf("2/n"); IoTPwmStart(PWM_OUTPUT_CH1,5,50); OS_MSleep(500); IoTGpioGetInputVal(13,&mode); printf("3/n"); IoTPwmStart(PWM_OUTPUT_CH1,8,50); OS_MSleep(500); if(mode == 1) { printf("4/n"); IoTPwmStart(PWM_OUTPUT_CH0,10,50); OS_MSleep(500); } else { printf("4/n"); IoTPwmStart(PWM_OUTPUT_CH0,6,50); OS_MSleep(500); } printf("5/n"); IoTPwmStart(PWM_OUTPUT_CH0,8,50); OS_MSleep(500); } static void MainThread(void *arg) { Servo_init(); Servo_reset(); while (1) { Servo_start(); } } void PWM_TestMain(void) { printf("Test Start\n"); if (OS_ThreadCreate(&g_main_thread,"MainThread",MainThread, NULL, OS_THREAD_PRIO_APP, 4096) != OS_OK) { printf("[ERR] Create PWMLED_Task Failed\n"); } } SYS_RUN(PWM_TestMain);
最后在编译选项中加上即可
"GO_sorting:app_GO"
总结
到此基本功能是实现了,但有很多缺陷如我没有直观地体现出来分类后各种棋子的数量,也并没有给他加上控制开始和停止的操作。(没有一个对是否仍有棋子未被分类的判断机制)这些后续可以通过增加显示屏、替换红外传感器为压感贴片或者使用摄像头去学习判等等···最遗憾的是这个小demo暂时还没有发挥出XR806及鸿蒙的一些特征,如联网、连蓝牙。仅仅是个突发奇想的点子,希望能起到抛砖引玉的作用。后面我也会继续尝试给他加上其他功能。再贴上一些前置学习内容:
官方文档:https://xr806.docs.aw-ol.com/XR806开发板引脚功能表:https://bbs.aw-ol.com/topic/496/资料释放-xr806鸿蒙开发板引脚功能表
SDK获取到编译烧录:https://bbs.aw-ol.com/topic/499/xr806鸿蒙开发实战1-实操下载xr806鸿蒙代码并编译烧写
鸿蒙的外设接口:文件接口的头文件在:
base\iot_hardware\peripheral\interfaces\kits
源码在:
device\xradio\xr806\adapter\hals\iot_hardware\wifiiot_lite
带有iot字样的接口就是鸿蒙的接口。
端口复用:
Harmony\device\xradio\xr806\xr_skylark\project\common\board\xr806_OHOS\board_config.c
可以看到关于pwm的相关端口配置
__xip_rodata static const GPIO_PinMuxParam g_pinmux_pwm[] = { { GPIO_PORT_A, GPIO_PIN_19, { GPIOA_P19_F4_PWM0_ECT0, GPIO_DRIVING_LEVEL_1, GPIO_PULL_NONE } }, { GPIO_PORT_A, GPIO_PIN_20, { GPIOA_P20_F4_PWM1_ECT1, GPIO_DRIVING_LEVEL_1, GPIO_PULL_NONE } }, { GPIO_PORT_A, GPIO_PIN_22, { GPIOA_P22_F4_PWM3_ECT3, GPIO_DRIVING_LEVEL_1, GPIO_PULL_NONE } }, { GPIO_PORT_A, GPIO_PIN_12, { GPIOA_P12_F3_PWM4_ECT4, GPIO_DRIVING_LEVEL_1, GPIO_PULL_NONE } }, { GPIO_PORT_A, GPIO_PIN_13, { GPIOA_P13_F3_PWM5_ECT5, GPIO_DRIVING_LEVEL_1, GPIO_PULL_NONE } }, { GPIO_PORT_B, GPIO_PIN_3, { GPIOB_P3_F4_PWM7_ECT7, GPIO_DRIVING_LEVEL_1, GPIO_PULL_NONE } }, };
项目中所用到的引脚:
一号舵机信号线---------PA20
二号舵机信号线---------PA19
红外传感信号线---------PA13
用面包板引出开发板上的电源跟地供外设共用。
-
F133评估版烧写固件后串口没有反应,求助
如题,烧写完f133的镜像后串口没有任何反应,有没有大佬能提供一个可以正常工作的固件,还有自己的固件不知道为什么选择了一些视频功能插件就没办法正常编译。
-
【XR806开发板试用】BLE试用之二:mesh&&PB-GATT配网
本文以 PB-GATT 方式对 Mesh 的配网场景进行演示说明。通过演示移动设备给 Mesh 节点配网场景,简要介绍 mesh 命令的基本使用方法。
对于XR806原生SDK用户,Mesh 命令集成在 cmd_mesh.c 文件中,烧录相应demo,通过 ble_demo 工程可以完成 mesh 节点配网场景演示,ble_demo 工程位于 XR806 SDK 的/project/demo/bluetooth/ble_demo 目录。具体可参考文档XR806_Mesh控制台命令_使用指南.pdf 。
对于XR806鸿蒙SDK用户,执行以下操作:
cd device/xradio/xr806/xr_skylark cp project/demo/wlan_ble_demo/gcc/deconfig .config make menuconfig
进入图像化配置界面,打开ble mesh的相关选项。
可以看到图形化配置界面:
在BLE host中可见配置:
进入mesh配置可见:
配置后保存退出。
继续执行
make build_clen make lib -j cd - hb build -f
可能遇到以下问题
问题1:可能会遇到空间不足报错的问题。
解决方案可以参考:
也可以取消
device\xradio\xr806\BUILD.gn
中其他内容的编译:
问题2:鸿蒙SDK没有BLE接口。
直接注释掉编译选项:
device/xradio/xr806/adapter/hals/BUILD.gn
编译完成后烧录镜像到开发板,通过串口打开命令行。
输入:
$ble init $mesh init
可见:
== XRadio BLE HOST V2.5.0 == [cmd] Mesh initialized [cmd] Use "pb-adv on" or "pb-gatt on" to enable advertising <ACK> 200 OK
选用 PB-GATT 的承载方式:
$mesh pb-gatt on
可见:
[bt] [INF] bt_mesh_prov_enable: Device UUID: 00000000-0000-0000-0000-00000000dddd [cmd] PB-GATT enabled <ACK> 200 OK $ ************************************************* [RandomAddress 57:F1:07:D8:B6:91 ]
同时需要手机提前下载安装nRF Mesh软件。
打开软件配网:
配网成功后,可以看到 nRF Mesh 网络列表看到该节点的信息,如下图。
点击红色方框,进入节点配置页面,可以看到节点的元素、模型等信息。
选择“Genenic On Off Server”模型进行操作:点击该模型选项,进入模型操作界面,如下图。进行模 型操作需要先进行“APP Key”绑定,点击“BIND KEY”,然后选择 App Key。
进行“Genenic On Off”:点击“ON”,就可以通过串口看到设备的 On/ Off 状态开了:
[cmd] onoff get(0) [cmd] onoff set(1) [cmd] onoff get(1) [cmd] onoff get(1) [cmd] onoff set(0) [cmd] onoff set(0)
说明:Genenic On Off 操作会先去获取 OnOff 状态,然后再配置,配置完成后再获取一次状态。
完整log如下:
target thread = main usage = 21, fragment = 0, maxFreeSize = 92740, totalFreeSize = 92740, waterLine = 26932 ==================================================================== Hello! OpenHarmony! System tag : OpenHarmony 1.1.2_LTS ==================================================================== target thread = pm usage = 23, fragment = 0, maxFreeSize = 90660, totalFreeSize = 90660, waterLine = 29012 use default flash chip mJedec 0x0 [FD I]: mode: 0x10, freq: 96000000Hz, drv: 0 [FD I]: jedec: 0x0, suspend_support: 1 target thread = Looper usage = 25, fragment = 1, maxFreeSize = 86836, totalFreeSize = 87636, waterLine = 32836 mode select:e target thread = tcpip usage = 27, fragment = 1, maxFreeSize = 84776, totalFreeSize = 85252, waterLine = 34420 target thread = umac usage = 29, fragment = 1, maxFreeSize = 82716, totalFreeSize = 83020, waterLine = 36652 target thread = workqueue usage = 31, fragment = 1, maxFreeSize = 80360, totalFreeSize = 80440, waterLine = 39320 target thread = rx_proc usage = 34, fragment = 1, maxFreeSize = 77524, totalFreeSize = 77604, waterLine = 42068 target thread = BH usage = 36, fragment = 1, maxFreeSize = 75464, totalFreeSize = 75544, waterLine = 44128 wlan information =================================================== firmware: version : R0-XR_C07.08.52.65_02.84 May 27 2021 11:41:33-Y02.84 buffer : 8 driver: version : XR_V02.05 mac address: in use : 0c:6e:88:3e:12:01 in use : 0c:6e:88:3e:12:02 ==================================================================== target thread = wpas usage = 40, fragment = 1, maxFreeSize = 69996, totalFreeSize = 70288, waterLine = 53648 wlan mode:a [VFS INF] SPIFFS mount success. platform information =============================================== XR806 SDK v1.2.0 Jan 19 2022 10:44:04 heap space [0x22a884, 0x247c00), size 119676 cpu clock 160000000 Hz HF clock 40000000 Hz sdk option: XIP : enable INT LF OSC : enable SIP flash : enable mac address: efuse : 80:74:84:05:ba:a0 in use : 0c:6e:88:3e:12:01 ==================================================================== target thread = MainThread usage = 49, fragment = 0, maxFreeSize = 60068, totalFreeSize = 60068, waterLine = 59604 target thread = hiview usage = 52, fragment = 0, maxFreeSize = 55504, totalFreeSize = 55504, waterLine = 64168 console init success hiview init success.target thread = console usage = 54, fragment = 1, maxFreeSize = 53444, totalFreeSize = 53468, waterLine = 66228 $ $ ble init target thread = LogMemTask usage = 51, fragment = 11, maxFreeSize = 51384, totalFreeSize = 57576, waterLine = 66228 ble controller open version : 9.1.19 build sha1 : v9.1.19-20210601 build date : Jun 1 2021 build time : 19:32:17 platform : xr806 ble rf_init done! target thread = LinkLayer usage = 58, fragment = 4, maxFreeSize = 47752, totalFreeSize = 49292, waterLine = 70380 target thread = LinkLayerHwEvent usage = 60, fragment = 4, maxFreeSize = 44668, totalFreeSize = 46208, waterLine = 73464 target thread = CoexEvent usage = 61, fragment = 4, maxFreeSize = 43632, totalFreeSize = 45172, waterLine = 74500 BLE INIT ALL DONE! BT Coex. Init. OK. == XRadio BLE HOST V2.5.0 == target thread = Zephyr usage = 69, fragment = 2, maxFreeSize = 35484, totalFreeSize = 36096, waterLine = 83576 target thread = Zephyr usage = 72, fragment = 2, maxFreeSize = 31376, totalFreeSize = 31988, waterLine = 87700 target thread = Zephyr usage = 74, fragment = 3, maxFreeSize = 29316, totalFreeSize = 29928, waterLine = 89744 target thread = Zephyr usage = 81, fragment = 3, maxFreeSize = 20504, totalFreeSize = 21116, waterLine = 98556 [bt] [WRN] set_flow_control: Controller to host flow control not supported [bt] [INF] bt_init: No ID address. App must call settings_load() [cmd] Bluetooth initialized [bt] [INF] bt_dev_show_info: Identity: C6:42:D9:8F:39:BB (random) [bt] [INF] bt_dev_show_info: HCI: version 5.0 (0x09) revision 0x0113, manufacturer 0x063d [bt] [INF] bt_dev_show_info: LMP: version 5.0 (0x09) subver 0x0113 [cmd] Settings Loaded <ACK> 200 OK $ mesh init == XRadio BLE HOST V2.5.0 == target thread = Zephyr usage = 84, fragment = 4, maxFreeSize = 16396, totalFreeSize = 17008, waterLine = 102680 [cmd] Mesh initialized [cmd] Use "pb-adv on" or "pb-gatt on" to enable advertising <ACK> 200 OK $ mesh pb-gatt on [bt] [INF] bt_mesh_prov_enable: Device UUID: 00000000-0000-0000-0000-00000000dddd [cmd] PB-GATT enabled <ACK> 200 OK $ ************************************************* [RandomAddress 57:F1:07:D8:B6:91 ] ************************************************* [cmd] Connected: 78:C4:1B:66:EC:45 (random) [cmd] Remote LMP version 5.0 (0x09) subversion 0x0000 manufacturer 0x0046 [cmd] LE Features: 0x00000000000179fd [cmd] LE conn param updated: int 0x0006 lat 0 to 500 [cmd] Provisioning link opened on PB-GATT [cmd] LE conn param updated: int 0x0027 lat 0 to 500 [cmd] LE data len updated: TX (len: 251 time: 17040) RX (len: 69 time: 5392) [bt] [INF] bt_mesh_provision: Primary Element: 0x0003: [cmd] Provisioning link closed on PB-GATT [cmd] Local node provisioned, net_idx 0x0000 address 0x0003 [cmd] Disconnected: 78:C4:1B:66:EC:45 (random) (reason 0x13) [cmd] Connected: 78:C4:1B:66:EC:45 (random) [cmd] Remote LMP version 5.0 (0x09) subversion 0x0000 manufacturer 0x0046 [cmd] LE Features: 0x00000000000179fd [cmd] LE conn param updated: int 0x0006 lat 0 to 500 [cmd] LE conn param updated: int 0x0027 lat 0 to 500 [cmd] LE data len updated: TX (len: 251 time: 17040) RX (len: 69 time: 5392) [bt] [WRN] trans_ack: No matching TX context for ack [cmd] onoff get(0) [cmd] onoff set(1) [cmd] onoff get(1) [cmd] onoff get(1) [cmd] onoff set(0) [cmd] onoff get(0) [cmd] onoff get(0) [cmd] onoff set(1) [cmd] onoff get(1) [cmd] onoff get(1) [cmd] onoff set(0) [cmd] onoff get(0)
-
【资源汇总】2021年哪吒开发板第三期成果汇报
点亮技能 开发者 简介 D1s裸奔驱动LCD,并运行xboot的各种风骚APP tripod9 D1s的RGB裸奔显示,运行xboot各种app D1s开源项目合集 whycan 目前各种基于D1/D1s绘制的开源开发板 毫无PS痕迹的MQ小麻雀定妆照,一体化(All-in-One)设计 mangogeek 芒果派大佬设计基于D1s的Linux小板麻雀 通过USB共享使D1s上的tina联网(RNDIS Gadget) SdtEE 一根USB线达到供电、联网、调试(ssh)、文件传输(smb/nfs/scp)的目的 D1s 目前的一些玩法:跑Ubuntu rootfs,显示图片,播放音频 (转载) SdtEE 通过chroot在D1s上启动一个带apt的ubuntu,显示图片和播放音频 一键生成可定制的Debian rootfs,支持D1/D1s riscv64(转载) SdtEE 跑一个脚本生成直接可用的rootfs,无需更多设置 终于在D1哪吒上面把跑InfoNES framebuffer 模拟器跑起来了 memory frambuffer在D1上的使用 D1哪吒开发板开机运行ucgui demo memory ucGUI移植到D1上跑demo 【资料释放】D1哪吒阿里小程序SDK释放 DOT小文哥 阿里基于D1哪吒开发板适配的阿里小程序框架源码释放 大佬在D1开发板上移植魂斗罗游戏 sunxiang buildroot搭建哪吒D1开发环境详细步骤,并且在HDMI显示器上玩上了魂斗罗(基于QT5) 动手让LVGL8带的Music-Demo音乐响起来 xfdr0805 LVGL8 自带音乐播放器Demo在哪吒扩展板上实现 阿里JS轻应用框架在D1上适配 DOT小文哥 JS轻应用框架语音面板demo 在D1开发板上运行Dahdi和Asterisk IPPBX xiaowen IP电话交换系统的哪吒扩展板 给D1 SDK 添加一个简单的helloworld package tigger Tina下可编译的helloworld的Demo 又一款开源显示框架GUI-lite,在D1上试试效果 BedRock 非常简便的开源GUI,在D1上实现 Neza-D1开发板学习之红外发送与接收篇 xfdr0805 用哪吒IO来发射红外信号 使用OpenCV实时显示USB摄像头画面到屏幕上 IAMLIUBO 借助OpenCV在哪吒上实时显示摄像头画面 【模块第三弹】哪吒中的LEDC的驱动 BedRock 实现了控制LEDC的接口 挪威科技大学使用全志D1哪吒开发板开设操作系统课程 Michael Engel 挪威科技大学的Michael Engel教授就在操作系统的课程中介绍并使用了哪吒D1及玄铁C906,并在课件中详细展示了如何在哪吒上玩转MIT的xv6 OS -
【XR806开发板试用】BLE试用之三:GATT读写示例
本示例通过演示 GATT 读写场景,简要介绍 GATT 命令的基本使用方法。
手机与开发板
烧录BLE工程后,在xr806的串口命令行依次执行ble init ble advertise on
开始广播。
成功后有如下提示:
$ ble advertise on ************************************************* [RandomAddress 62:77:A4:D1:10:44 ] ************************************************* [cmd] Advertising started <ACK> 200 OK
注册 GATT 服务,往串口输入命令,结果如下:
$ gatt metrics on [cmd] Registering GATT metrics test Service. [cmd] GATT write cmd metrics on. <ACK> 200 OK
后需要下载nRF connect软件对周围设备扫描:
连接成功后可以看到 nRF Connect 跳转到以下界面了:
同时串口可以看到提示:
[cmd] Connected: 72:07:2F:49:AD:A1 (random) [cmd] Remote LMP version 5.0 (0x09) subversion 0x0000 manufacturer 0x0046 [cmd] LE Features: 0x00000000000179fd [cmd] LE conn param updated: int 0x0006 lat 0 to 500 [cmd] LE conn param updated: int 0x0027 lat 0 to 500
红色部分的 Service 即是步骤 4 所创建的 GATT 服务。点开“Unknown Service”,可以看到注册的服务 包括一个可读可写的属性。
进行读写操作:如写入值“0x010203”,按照下图的红色序号“①->②->③”操作,然后在红色序 号④可以看到数据正常写入。此时再进行读操作,点击蓝色的①,可以在蓝色序号②的位置看到读取的结果如下:
开发板互联
两块评估板完成烧写后,复位即可,示例代码自动运行。
分别执行
ble init
评估板 B 执行“ble advertise on”命令开始广播:
$ble advertise on ************************************************* [RandomAddress 5F:6F:67:DA:79:61 ] ************************************************* [cmd] Advertising started <ACK> 200 OK
评估板 B 注册 GATT 服务,往串口输入命令
$gatt metrics on [cmd] Registering GATT metrics test Service. [cmd] GATT write cmd metrics on. <ACK> 200 OK
评估板 A 开始扫描设备:
$>ble scan on
可以看到一大串扫描结果,执行一段时间后执行
ble scan off
关闭扫描
可以找到对应扫描结果地址
... [cmd] [DEVICE]: 5F:6F:67:DA:79:61 (random), AD evt type 4, RSSI -23 Xradio C:0 S:1 D:0 SR:1 E:0 Prim: LE 1M, Secn: No packets ...
评估板 A 开始连接 B:
$>ble connect 5F:6F:67:DA:79:61 random
连接成功后,A 有以下打印:
************************************************* [RandomAddress 56:25:4C:81:C7:1E ] ************************************************* [cmd] Connection pending <ACK> 200 OK $ [cmd] Connected: 5F:6F:67:DA:79:61 (random)
同时 B 也有成功连接的打印:
[cmd] Connected: 56:25:4C:81:C7:1E (random) [cmd] Remote LMP version 5.0 (0x09) subversion 0x0110 manufacturer 0x063d [cmd] LE Features: 0x00000000000179ff
进行服务的查找,往 A 评估板输入命令结果:
$>gatt discover $ [cmd] Descriptor 2800 found: handle 1 [cmd] Descriptor 2803 found: handle 2 [cmd] Descriptor 2a05 found: handle 3 [cmd] Descriptor 2902 found: handle 4 [cmd] Descriptor 2800 found: handle 5 [cmd] Descriptor 2803 found: handle 6 [cmd] Descriptor 2a00 found: handle 7 [cmd] Descriptor 2803 found: handle 8 [cmd] Descriptor 2a01 found: handle 9 [cmd] Descriptor 2803 found: handle a [cmd] Descriptor 2aa6 found: handle b [cmd] Descriptor 2800 found: handle c [cmd] Descriptor 2803 found: handle d [cmd] Descriptor 12345678-1234-5678-1234-56789abcde02 found: handle e [cmd] Discover complete
可以看到,“12345678-1234-5678-1234-56789abcde02”是评估板 B 注册的属性,可读可写,其 handle 是 e。
进行 GATT 写操作:评估板 A 往 handle 是 e 的属性写字符串“ab”:
$>gatt write e 0 ab string [cmd] Write pending <ACK> 200 OK $ [cmd] Write complete: err 0x00
进行 GATT 读操作:评估板 A 往 handle 是 e 的属性读数据:
gatt read e [cmd] Read pending <ACK> 200 OK $ [cmd] Read complete: err 0x00 length 2 [cmd] Read Value: 6162
其中 61/62 正是 a/b 的 ASCII 码,读写成功。
-
XR806开发板FreeRTOS SDK试用
1、根据文档下载SDK
git clone ssh://YOURNAME@sdk.allwinnertech.com/git_repo/XR806/xr806_sdk/xr806_sdk.git -b xr806_sdk
YOURNAME是自己在客户平台的用户名,我这里的环境是官方给的Ubuntu14,之前编译D1的tinaLinux用的。
拉代码之前务必确认正确添加了本机公钥。
2、配置
可以看看目录结构:
allwinner@allwinner-VirtualBox:~/xr806_sdk$ tree -L 1 . ├── bin ├── ChangeLog.md ├── chip.mk ├── config.mk ├── gcc.mk ├── include ├── Kconfig ├── lib ├── Makefile ├── project ├── README.md ├── src └── tools 6 directories, 7 files
打开README.md查看:
# XR806 SDK XR806 SDK supports XR806 series wireless MCUs. ## Configuration - Edit "gcc.mk" to define GCC path to your own path, eg. ``` CC_DIR = ~/tools/gcc-arm-none-eabi-8-2019-q3-update/bin ``` ## Building - Building commands ``` $ # make sure in SDK top dir $ make PRJ=${prj} defconfig or cp ${prj_defconfig} .config # eg. make PRJ=demo/wlan_demo defconfig or copy project/demo/wlan_demo/gcc/defconfig .config $ make menuconfig # check configuration, like board/XTAL/XIP/CacheSize/... $ make lib # build libraries and copy them to "lib" $ make lib_clean # remove files in "src" generated by `make lib` $ make lib_install_clean # Remove libraries in "lib" generated by `make lib` $ make # build the executable binary $ make clean # remove files generated by `make` $ make image # create the image file $ make image_clean # remove files generated by `make image` $ make objdump # generate the disassembled file $ make build # same as `make lib && make && make image` $ make build_clean # same as `make image_clean clean lib_clean lib_install_clean` ``` ## Links - SDK: https://github.com/XradioTech/xr806-sdk.git - WiKi: https://github.com/XradioTech/xradiotech-wiki.git - DOC: https://docs.xradiotech.com
根据提示需要先指定编译器的位置
下载一下相应的编译器并解压:
gcc-arm-none-eabi-8-2019-q3-update-linux.tar.bz2tar -jxvf gcc-arm-none-eabi-8-2019-q3-update-linux.tar.bz2
然后修改gcc.mk中指向的目录即可,如下:
CC_DIR := ~/gcc-arm-none-eabi-8-2019-q3-update/bin
后面详细列出了make方式,注意要在SDK最顶层下执行。
3、编译DEMO
首先需要执行一下:
make menuconfig
然后保存退出即可。
然后执行:
make PRJ=demo/hello_demo
可以看到结果:
text data bss dec hex filename 39752 1576 2248 43576 aa38 hello_demo.elf make[2]: Leaving directory `/home/allwinner/xr806_sdk/project/demo/hello_demo/gcc' make[1]: Leaving directory `/home/allwinner/xr806_sdk/project/demo/hello_demo/gcc' /home/allwinner/xr806_sdk
4、制作镜像
进入上一步的demo目录下:
cd project/demo/hello_demo/gcc/
执行
make image
可以看到:
Flash Layout: sec bin 0 boot_40M.bin : flash_offs: 0x00000000( 0K) data_size: 0x00002F28( 12K) sec bin 1 app.bin : flash_offs: 0x00004000( 16K) data_size: 0x00004920( 19K) sec bin 2 app_xip.bin : flash_offs: 0x00029800( 166K) data_size: 0x000058D0( 23K) generate image: xr_system.img cp -t ../../../../out/ ../image/"xr806"/*.bin ../image/"xr806"/xr_system.img *.map
回到SDK根目录下可以看到out文件夹,进入后可见输出文件:
allwinner@allwinner-VirtualBox:~/xr806_sdk/out$ ls app.bin app_xip.bin boot_40M.bin hello_demo.map sys_sdd_40M.bin wlan_bl.bin wlan_fw.bin xr_system.img
5、烧录
在SDK的tools文件夹下可见有烧录工具:
allwinner@allwinner-VirtualBox:~/xr806_sdk/tools$ ls Blink.apk fs_img_tools mkimage.exe phoenixMC.dll settings.ini SoundConfig.apk config HcidumpXr.7z mkimage_mac64 phoenixMC.exe settings_mac.ini efuse_tool map_parse_gcc_v3.py phoenixMC phoenixMC_mac64 signpack.sh etfGuiTool.exe mkimage phoenixMC_cli.exe sdd_editor SmartConfig.apk
由于想偷懒,没在虚拟机下烧录,直接把img和工具都拖到Windows下:
完成烧录:
6、查看输出
我是用的是putty,波特率115200
熟悉的helloworld: