打印
[uCOS/RTOS]

RT-Thread应用创新设计大赛 + 麻雀1号 + 从开箱到项目文档

[复制链接]
2122|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
鱼柯1412|  楼主 | 2020-6-7 18:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 鱼柯1412 于 2020-6-7 18:11 编辑

拿到麻雀的板子很长时间了,期间在做另外项目,有点坑要填,所以...晚了一段时间,打算将麻雀从开箱到项目完成文档放在一个帖子里。
使用麻雀的过程中,个人能力的问题,遇到一些坑,填坑的记录放在自己的公众号上(其实就是一些私人笔记),所以如果你在其他地方看到和本片帖子相关的内容,不要说这是从xx地方抄来的...
说了那么多废话,上开箱
[开发板]麻雀1号-01_开箱
搞了一块麻雀1号,开心,尝试下不同的MCU。板子是从rt-thread那里搞来的,确实小巧的很。
麻雀一号开发板采用的主控芯片是 BK7252 , 是一款高性能 WiFi 模块,采用高集成的无线射频芯片,内部集成 2.4GHz Wi-Fi 1T1R 先进技术,支持摄像头图像输出,拥有最佳的功耗性能、射频性能、稳定性、通用性和可靠性,适用于各种应用和不同产品需求。模块内部拥有 512KB 内嵌 RAM 和 4Mbyte Flash 空间,CPU 主频高达 180Mhz。并且集成了天线开关、功率放大器、低噪放大器、过滤器、电源管理模块, 支持 802.11e 以及 WMM-PS 协议, 支持 WPA、WPA2 和 WAPI 安全协议,同时集成了蓝牙 BLE 收发器,支持 BLE4.2,支持主机或从机模式。
                                                                                                                                                                        RT-THREAD BK7252 麻雀一号开发板使用文档_20191112
片子是Beken 博通集成电路(上海)的,上他们官网转了一圈。没有资料,流汗。所有的芯片都只是弹窗介绍下功能,甚至连性能参数也没有,datasheet更是不用考虑了。


file://D:/WorkSpace/95_Subscription/%E5%BC%80%E5%8F%91%E6%9D%BF/%E9%BA%BB%E9%9B%801%E5%8F%B7/$%7BPic%7D/beken.png?lastModify=1591523698
好吧,终于在rt-thread提供的包里面找到了datasheet。只有25页,里面只有功能描述如下图这样的。哎,这么多年看过最简单的datasheet。
file://D:/WorkSpace/95_Subscription/%E5%BC%80%E5%8F%91%E6%9D%BF/%E9%BA%BB%E9%9B%801%E5%8F%B7/$%7BPic%7D/beken_datasheet.png?lastModify=1591523698
板上资源
生活还是要继续, 看下板上资源,图来自于 RT-THREAD BK7252 麻雀一号开发板使用文档_20191112
file://D:/WorkSpace/95_Subscription/%E5%BC%80%E5%8F%91%E6%9D%BF/%E9%BA%BB%E9%9B%801%E5%8F%B7/$%7BPic%7D/board_up.png?lastModify=1591523698
file://D:/WorkSpace/95_Subscription/%E5%BC%80%E5%8F%91%E6%9D%BF/%E9%BA%BB%E9%9B%801%E5%8F%B7/$%7BPic%7D/board_down.png?lastModify=1591523698
开箱使用
即是rt-thread出品的,finsh必然自带。上电,usb到pc,打开secureCRT,tab。出厂的一些cmd,大概瞄了一下。配一下网。
wifi ap scan
wifi ap join {ssid} {password}
连到家里wifi, ntp_sync  同步一下时间,
Get local time from NTP server: Sun Apr 12 20:05:57 2020
The system time is updated. Timezone is 8.
可以,最基本的功能,wifi没问题了,其他的按键,lcd,led肉眼可见的功能,看看,按按就好。
代码更新方式
数据手册里有这样一句化
Multiplexing program download and JTAG interface
                                                                                                                                                                                                                                                                                BK7252_Data_Sheet_V1.0
之所以要写开箱,是这个板子的代码更新的方式。按rt-thread手册所述,有三种:
  • 无线烧录器
  • 有线烧录器
  • OTA升级

没有看到详细说明,只能自己猜猜:
  • 我最好奇的是无线烧录,这个无线烧录应该是一个webserver,通过wifi和pc建立连接后,浏览器访问无线烧录器,通过http post 到 无线烧录器,然后无线烧录器将bin文件 download到target上,可是没看到无线烧录器和核心板的接口管脚是?按框图理解,应该是uart。
  • 有线的烧写工具,上位软件专有的烧写软件(主要是烧写算法),pc->有线烧写工具-spi->target。
  • ota升级是要bootloader和数据转存的app。这部分只能通过先把带有[bootloader, app] 的bin文件通过1,2方法下载到target中以后才能使用。

编译,生成all.bin 遇到首坑
file://D:/WorkSpace/95_Subscription/%E5%BC%80%E5%8F%91%E6%9D%BF/%E9%BA%BB%E9%9B%801%E5%8F%B7/$%7BPic%7D/scons_error.png?lastModify=1591523698
后面发现问题,自己拿到rt-thread喜欢先menuconfig一下,看看板上实现哪些功能等等。menuconfig 每操作一次,就会把当前路径的rt_config.h的文件修改一下,而scons需要从这个文件找项目的依赖,这个就是问题症结了。这个sdk中的rt_config.h 可能前期用menuconfig配置过,后面一直手动添加依赖宏。换会初始的rt_config.h, 嗯,还好编译成功了。
无线烧录
按照手册打包bin文件
file://D:/WorkSpace/95_Subscription/%E5%BC%80%E5%8F%91%E6%9D%BF/%E9%BA%BB%E9%9B%801%E5%8F%B7/$%7BPic%7D/package.png?lastModify=1591523698
浏览器打开无线烧录器默认的 IP 为192.168.169.1,定位到固件位置,上传固件就可以了。
file://D:/WorkSpace/95_Subscription/%E5%BC%80%E5%8F%91%E6%9D%BF/%E9%BA%BB%E9%9B%801%E5%8F%B7/$%7BPic%7D/download.png?lastModify=1591523698
先点个灯
file://D:/WorkSpace/95_Subscription/%E5%BC%80%E5%8F%91%E6%9D%BF/%E9%BA%BB%E9%9B%801%E5%8F%B7/$%7BPic%7D/led_sch.png?lastModify=1591523698
官方的{sdk_root}/test/gpio_demo.c 添加了下面代码;编译
// LED1_PIN_NUM p13
static void pin_led_blink(void)
{
     int i = 0;
     rt_pin_mode(LED1_PIN_NUM, PIN_MODE_OUTPUT);
     while (i++ < 10)
     {
         rt_pin_write(LED1_PIN_NUM, PIN_LOW);
         rt_thread_mdelay(500);
         rt_pin_write(LED1_PIN_NUM, PIN_HIGH);
         rt_thread_mdelay(500);
     }
}
MSH_CMD_EXPORT(pin_led_blink, blink led);
顺便再试试ota升级, ota打包,特别注意版本号,应该要不等于当前内部版本号
file://D:/WorkSpace/95_Subscription/%E5%BC%80%E5%8F%91%E6%9D%BF/%E9%BA%BB%E9%9B%801%E5%8F%B7/$%7BPic%7D/ota_package.png?lastModify=1591523698
配置本地http服务器
file://D:/WorkSpace/95_Subscription/%E5%BC%80%E5%8F%91%E6%9D%BF/%E9%BA%BB%E9%9B%801%E5%8F%B7/$%7BPic%7D/config_server.png?lastModify=1591523698
http ota,可以了,官方这个ota好像有断点续传功能,http_ota拉文件,失败了好几次,每次都是从上次失败的地方继续拉。
file://D:/WorkSpace/95_Subscription/%E5%BC%80%E5%8F%91%E6%9D%BF/%E9%BA%BB%E9%9B%801%E5%8F%B7/$%7BPic%7D/upload_scuessed.png?lastModify=1591523698
tab键,可以了,刚才添加的函数,运行一下,结束本篇;
file://D:/WorkSpace/95_Subscription/%E5%BC%80%E5%8F%91%E6%9D%BF/%E9%BA%BB%E9%9B%801%E5%8F%B7/$%7BPic%7D/run.png?lastModify=1591523698
总结:
这东西没有rt-thread给的sdk,还真不好搞
  • 芯片手册,几乎没有;
  • menuconfig同时手动配置rt_config.h是一个坑;
  • http ota 每次update后,都要重新wifi ap scan, wifi ap join,不方便,调试阶段还是用无线烧录器;
  • 但是这里的无线烧录器和http_ota的断点续传我很喜欢;





使用特权

评论回复

相关帖子

沙发
鱼柯1412|  楼主 | 2020-6-7 18:12 | 只看该作者
文档编辑有问题,图片有本地链接,,先这样吧,后面会注意的

使用特权

评论回复
板凳
鱼柯1412|  楼主 | 2020-6-7 18:14 | 只看该作者
本帖最后由 鱼柯1412 于 2020-6-12 15:58 编辑

[开发板]麻雀1号-02_OTA加速
用了麻雀1号几次,发现调试和下载是个问题;每次编译完成,如果通过无线烧录器,烧录完成后,需要重新连接wifi;通过OTA升级也有同样的问题,升级完成后,通过 finsh ,wifi w0 scan, wifi w0 join ssid password 不胜其烦;
麻雀上的wifi
麻雀板上有两个网络设备ap 和 w0, 分别时AP模式的设备和station模式的设备;
AP模式: Access Point,提供无线接入服务,允许其它无线设备接入,提供数据访问,一般的无线路由/网桥工作在该模式下。AP和AP之间允许相互连接。
Station模式: 类似于无线终端,Station模式本身并不接受无线的接入,它可以连接到AP,一般无线网卡即工作在该模式。
要让麻雀连上网,使用 w0 网络设备;即使你用 wifi ap join ssid passward 其最后连上的也是 w0;
可以用ap模式wifi ap ap sparrow (配置一个无密的ap) 和w0模式同时启动,手机通过ap接到麻雀上网;
wifi自动连接
sdk中与wifi 连接相关的几个关键的文件夹
./bk7221u_release/drivers/wlan/
./bk7221u_release/rt-thread/components/drivers/wlan/
麻雀上的WiFi连接通常使用下面的命令进行网络连接;
cmd:   wifi w0 join ssid {password}
从cmd到最终执行的流程大概是下图这样,在进行快速网络连接时,  _waln_advance_connet 会查看是否有wifi 快速连接的配置信息,如果有则直接连接;没有的话,则根据有ssid,  password 进行带密码配置网络;每次连接成功后,_wifi_connect_done 会将wifi网络网络连接参数通过 drv_wlan_fast_connect.c 中的 wlan_fast_connect_info_write  存储在flash 非文件系统中 ( easyflash 的类似键值数据)。 下次连接时,就可以通过不带password 连接 wifi 。
cmd:wifi
wifi命令的联网与上述类似;只不过,wifi 命令是通过 wifi_default 函数读文件系统中的网络连接配置文件,进行网络连接的;这里的网络连接参数文件是通过 wifi cfg ssid password 命令配置,以 json 文件存储在文件系统中;
文件./bk7221u_release/rt-thread/components/drivers/wlan/wlan_cmd.c 中有 WIFI_SETTING_FN 中关于配置文件路径的定义;
明白以上两种方式,自动联网就比较简单了;
上电自动联网
wifi 设备是通过自动初始化 INIT_DEVICE_EXPORT(beken_wlan_hw_init);   进行硬件的一些初始化;借[RT-THREAD编程指南] 中的一张图,看各INIT 的启动顺序;
wifi 自动连接放到 INIT_ENV_EXPORT 中就可以,我这里借,cmd:wifi 编一个非常简单的函数, 我这里能自动连接的前提是, wifi 配置信息已在文件系统中了;有文件系统处理就好办了;有配置文件,拉配置文件进行自动配置;没有配置文件,输出要配置的提示信息就好;借助已实现的 compontents/wlan/wlan_cmd 很愉快的可以实现这个功能;实现这个的方法很多,如直接调用 wifi_default。下面的函数其实也是间接调用 wifi_default, open  的文件地址要与 wifi_cmd.c 的宏 WIFI_SETTING_FN 一致, 可以在哪个头文件定义一下,可以直接在 rtconfig.h 中定义下,如果编译速度快的话;
但现实是残酷的,麻雀变砖了;
翻了下main, 发现麻雀的板子并没有使用自动初始化,相关初始化都手动放在 main 函数处;auto_link_wifi 函数放到 main 搞定;
ota加速
ota升级时,手动输入http 地址很麻烦,仿照 wifi_default 的实现方法,实现了一个加速ota的功能;cfg 将 http 信息存在文件系统中, ota时读这个文件,如果有配置http 地址,则按地址 ota 就好。
#define OTA_SETTING_FILE "/sd/ota.json"
char ota_addr[64] = {0};

#ifdef PKG_USING_CJSON
int ota_read_cfg(const char *filename)
{
     int fd;
     cJSON *json = RT_NULL;

     fd = open(filename, O_RDONLY, 0);
     if (fd < 0)
     {
         /* no setting file */
         return -1;
     }

     if (fd >= 0)
     {
         int length;

         length = lseek(fd, 0, SEEK_END);
         if (length)
         {
             char *json_str = (char *) rt_malloc(length);
             if (json_str)
             {
                 lseek(fd, 0, SEEK_SET);
                 read(fd, json_str, length);

                 json = cJSON_Parse(json_str);
                 rt_free(json_str);
             }
         }
         close(fd);
     }

     if (json)
     {
         cJSON *ota = cJSON_GetObjectItem(json, "ota_addr");

         if (ota)
         {
             rt_strncpy(ota_addr, ota->valuestring, sizeof(ota_addr) - 1);
         }

         cJSON_Delete(json);
     }

     return 0;
}


int ota_save_cfg(const char *filename)
{
     int fd;
     cJSON *json = RT_NULL;

     fd = open(filename, O_RDONLY, 0);
     if (fd >= 0)
     {
         int length;

         length = lseek(fd, 0, SEEK_END);
         LOG_D("read file len %d", length);
         if (length)
         {
             char *json_str = (char *) rt_malloc(length);
             if (json_str)
             {
                 lseek(fd, 0, SEEK_SET);
                 read(fd, json_str, length);

                 json = cJSON_Parse(json_str);
                 LOG_D("parse json addr %p", json);
                 rt_free(json_str);
             }
         }
         close(fd);
     }
     else
     {
         /* create a new ota.json */
         fd = open(filename, O_WRONLY | O_TRUNC, 0);
         if (fd >= 0)
         {
             json = cJSON_CreateObject();
             if (json)
             {
                 cJSON *ota = cJSON_CreateObject();

                 if (ota)
                 {
                     char *json_str;

                     cJSON_AddStringToObject(json, "ota_addr", ota_addr);

                     json_str = cJSON_PrintUnformatted(json);
                     if (json_str)
                     {
                         write(fd, json_str, rt_strlen(json_str));
                         cJSON_free(json_str);
                     }
                 }
             }
         }
         close(fd);

         return 0;
     }

     if (json)
     {
         cJSON *ota = cJSON_GetObjectItem(json, "ota_addr");
         LOG_D("create new file ota point ");
         if (!ota)
         {
             ota = cJSON_CreateObject();
             cJSON_AddStringToObject(json, "ota_addr", ota_addr);
         }
         else
         {
             LOG_D("recofig ota");
             cJSON_ReplaceItemInObject(json, "ota_addr", cJSON_CreateString(ota_addr));
         }


         fd = open(filename, O_WRONLY | O_TRUNC, 0);
         if (fd >= 0)
         {
             char *json_str = cJSON_PrintUnformatted(json);
             if (json_str)
             {
                 write(fd, json_str, rt_strlen(json_str));
                 cJSON_free(json_str);
             }
             close(fd);
         }
         cJSON_Delete(json);
     }
     return 0;
}
#endif

int ota(int argc, char *argv[])
{
     if (argc == 3)
     {
         if (strcmp(argv[1], "cfg") == 0)
         {
             memset(ota_addr, '\0', sizeof(ota_addr));
             memcpy(ota_addr, argv[2], strlen(argv[2]));
             rt_kprintf("ota_addr: %s strlen: %d\r\n", ota_addr, strlen(ota_addr));
#ifdef PKG_USING_CJSON
             ota_save_cfg(OTA_SETTING_FILE);
#endif
         }
     }
     else
     {
#ifdef PKG_USING_CJSON
         ota_read_cfg(OTA_SETTING_FILE);
         rt_kprintf("ota address: %s\r\n", ota_addr);
         if (strlen(ota_addr) > 30)
         {
             extern void http_ota(uint8_t argc, char **argv);
             http_ota(2, argv);
         }
         else
         {
             rt_kprintf("ota address Error\r\n");
         }
#endif
     }
}
MSH_CMD_EXPORT(ota, ota update or ota update http address cfg);
基本实现功能,虽然只是少敲了一行字,但也是很开心的;
总结
  • 麻雀这块板子的好多初始化采用手动初始化,在主线程里;所以遇到采用 EXPORT 的初始化不成功后,看看是不是 main 线程的影响,初始化是不是依赖其他设备;
  • 其实 wifi 连接,使能文件系统,配置 WIFI_SETTING_FN 后,连接也就一个 w ,tab, enter 搞定;
  • 换其他网络,拔出sd, 修改下setting.json, ota.json, 好了,不用烦人的wifi scan ...


PS: 麻雀变砖解救办法
无线烧录器,但要擦除整个全部flash

使用特权

评论回复
地板
鱼柯1412|  楼主 | 2020-6-7 18:16 | 只看该作者
本帖最后由 鱼柯1412 于 2020-6-19 09:33 编辑

[开发板]麻雀1号-03_menuconfig
前言
一般嵌入式开发的流程是:编辑, 编译,下载,调试,IDE将这些功能合并到一个平台上;但是总有少数喜欢折腾的人,希望跳出IDE的舒适圈,折腾折腾;
RT-Thread 完整版是一个学习这种折腾的好的平台,编辑工具随你喜欢,vscode,sourceinsight, notepad++,vim...; 项目构建工具使用 scons; 编译链接工具 gcc, armlang随你喜欢;下载调试随你擅长,回到keil或者iar可以,亦或用segger的ozone也行。取自己所擅长的东西,快速完成才是王道。
RT-Thread 引入的 menuconfig 也是加速设计的一个工具;rt-thread/tools/kconfig-frontends目录下的软件就是用来配置内核,外设,软件包...你设计的,需要可配置的文件;
menuconfig
Kconfig is the configuration language used by the Linux kernel. This package is a simple copy of the frontends and the parser found in the Linux kernel source tree, with very minor changes to adapt them to being built out of the kernel build infrastructure.
其基本原理是,读取Kconfig文件,图形化显示在中断,当你勾选(bool),设置(string,int)时,会生成.config文件,后面经.config文件的处理后,生成一些宏并写入到rtconfig.h中;直白的说:menuconfig 生成rtconfig.h文件中的一些 #define xxx,编译时,根据这些 #define xxx 和源文件的条件编译项,生成target(elf), 删除一些调试信息后得到bin或hex。
但是,menuconfig本身只负责提供menuconfig工作的这一套逻辑,比如说通过上下左右调整光标,Enter选中等,并不负责提供内容。menuconfig运行之后会读取Kconfig、读取/写入.config文件,Kconfig提供菜单项的内容,.config用来记录菜单项的选择值。通过menuconfig(windows env), scons --menuconfig (linux)可打开配置界面。
所以正确使用menuconfig的一个关键是:要明白代码的依赖关系,并把这种依赖关系用Kconfig文件体现出来;
至于Kconfig的编写,百度,或者麻雀1号bsp中现成示例;
麻雀1号无法使用menuconfig的原因
拿到麻雀1号的bsp,会发现,无法使用menuconfig的,分析了下原因
  • bsp中部分文件通过 Kconfig 可控;而部分文件不能通过 Kconfig 文件可控;
  • 开发过程中增加软件包或功能过程中,没有增加相应的 Kconfig 文件,为了简单快速开发,采用简单暴力的手法,直接在rtconfig.h 添加 宏定义,这样通过menuconfig操作后,手动添加的宏定义就被自动删除了 ;

解决方案
知道问题,解决起来就比较简单,主要思路是:
  • 如果使用了 package ,尽量在menuconfig对其进行配置;
  • 如果是自己增加的组件,编写对应的 Kconfig 文件,并在主Kconfig中将其source;
  • 特殊增加的,添加对应的config 项目;

第一项,比较简单,时间问题;
解决第一项
比较简单,主要是littefs中,LFS_BLOCK_CYCLES 必须配为-1,否则可能会导致你使用无线烧录器; 断言失败,程序假死。具体是什么错误,忘记截图了;
解决第二项
第二项简单说一下,bsp中有个components, 主要是麻雀的音频的一些组件,这里以前是手动增加宏定义,添加编译的;
编写对应的Kconfig 文件
menu "sparrow components Config"

config CONFIG_VOICE_CHANGER
     int "config voice changer"
     default 0

config PKG_USING_PLAYER
     bool "Using player"
     default y

config PLAYER_ENABLE_NET_STREAM
     bool "using net stream"
     default y
     if PKG_USING_PLAYER
         config PLAYER_USING_EXAMPLE00
         bool "using play example0"
         default y
         config PLAYER_USING_EXAMPLE02
         bool "using play example1"
         default y
     endif
endmenu
主Kconfig中source
这样就可以了;
解决第三项
麻雀中的I2C2,和 I2S是其独有的,所以把这部分加入配置
config RT_USING_I2C2
     bool "Using I2C2"
     default n

config RT_USING_I2S
     bool "Using I2S"
     default n测试
配置sparrow components等
编译,没有问题;
添加软件包signalled 添加signalled
添加个signalled 测试下
注意,这里不建议直接在bsp所在目录进行 pkgs --update 主要是,这里面使用的软件包,和目前的软件包命名不一样;pkgs --update 本来会删除旧包,下载新包,但是这里不会删除旧包。
看下 pkgs --update 的错误信息。
cmd_package_update 454 WARNING Missing path D:\bk7221u_release\packages\webclient-latest
cmd_package_update 455 WARNING If you manage this package manually, Env tool will not update it.
cmd_package_update 454 WARNING Missing path D:\bk7221u_release\packages\netutils-latest
cmd_package_update 455 WARNING If you manage this package manually, Env tool will not update it.
cmd_package_update 455 WARNING If you manage this package manually, Env tool will not update it.
这就是一会手动,一会自动添加引起的问题;即使 pkgs --update更新软件包完成后,编译也会失败;
解决办法:
  • 在其他bsp中将所需pkgs --update 后,将拉下来的packages移动到 麻雀/packages路径;
  • 麻雀bsp下,使用 menuconfig 使能对应的软件包;

添加完signalled后,编译没问题;开心...
signalled测试文件 #include <rtthread.h>
#include <rtdevice.h>
#include "signal_led.h"

#define DBG_ENABLE
#define DBG_LEVEL   DBG_LOG
#define DBG_COLOR
#define DBG_SECTION_NAME    "t.Led"
#include "rtdbg.h"
/* defined the LED pin */
// #define LED_PIN_NUM 30
#define LED0_PIN_NUM 12
#define LED1_PIN_NUM 13
// #define LED2_PIN_NUM 27

#define LED0    LED0_PIN_NUM
#define LED1    LED1_PIN_NUM


//定义信号灯对象句柄
led_t *led0 =  NULL;
led_t *led1 =  NULL;
//定义内存操作函数接口
led_mem_opreation_t led_mem_opreation;

/*  设置信号灯一个周期内的闪烁模式
  *  格式为 “亮、灭、亮、灭、亮、灭 …………” 长度不限
  *  注意:  该配置单位为毫秒,且必须大于 “LED_TICK_TIME” 宏,且为整数倍(不为整数倍则向下取整处理)
  *          必须以英文逗号为间隔,且以英文逗号结尾,字符串内只允许有数字及逗号,不得有其他字符出现
  */

char *led_blink_mode[] = {
"500,500,", //1Hz闪烁
"50,50,",   //10Hz闪烁
"0,100,",   //常灭
"100,0,",   //常亮
"100,100,100,1000,",//非固定时间
"500,100,",
};

//定义开灯函数
void led0_switch_on(void)
{
     rt_pin_write(LED0, PIN_LOW);
}

//定义关灯函数
void led0_switch_off(void)
{
     rt_pin_write(LED0, PIN_HIGH);
}

//定义开灯函数
void led1_switch_on(void)
{
     rt_pin_write(LED1, PIN_LOW);
}

//定义关灯函数
void led1_switch_off(void)
{
     rt_pin_write(LED1, PIN_HIGH);
}

void blink_over_callback(led_t *led_handler)
{
     if (led_handler == led0)
     {
         LOG_I("led0 blink over callback");
     }
     else if (led_handler == led1)
     {
         LOG_I("led1 blink over callback");
     }
}

static void led_run(void *parameter)
{
     while(1)
     {
         led_ticks();
         rt_thread_mdelay(LED_TICK_TIME);
     }
}

int rt_led_timer_init(void)
{
     rt_pin_mode(LED0, PIN_MODE_OUTPUT);
     rt_pin_mode(LED1, PIN_MODE_OUTPUT);
     
     led_mem_opreation.malloc_fn = (void* (*)(size_t))rt_malloc;
     led_mem_opreation.free_fn = rt_free;
     led_set_mem_operation(&led_mem_opreation);
     
     //初始化信号灯对象
     led0 = led_create(led0_switch_on, led0_switch_off);
     led1 = led_create(led1_switch_on, led1_switch_off);
   
     //设置信号灯工作模式
     led_set_mode(led0, LOOP_PERMANENT, led_blink_mode[0]);
     led_set_mode(led1, LOOP_PERMANENT, led_blink_mode[1]);
     //设置信号灯闪烁结束回调函数
     led_set_blink_over_callback(led0, blink_over_callback);
     led_set_blink_over_callback(led1, blink_over_callback);
     
     //开启信号灯
     led_start(led0);
     led_start(led1);
     
      
     rt_thread_t tid = RT_NULL;
     tid = rt_thread_create("signal_led",
                             led_run,
                             RT_NULL,
                             512,
                             RT_THREAD_PRIORITY_MAX/2,
                             100);
     if (tid != RT_NULL)
     {
         LOG_I("start signal led thread");
         rt_thread_startup(tid);
     }
     return RT_EOK;
}
// not recommended using auto init, didn't known app init squence
// INIT_APP_EXPORT(rt_led_timer_init);
MSH_CMD_EXPORT(rt_led_timer_init, led timer);

//中途切换模式测试
void led_switch(int argc, char *argv[])
{
     led_t *led = NULL;
     uint8_t loop = 0;
     uint8_t mode = 0;
     if (4 == argc)
     {
         if (!rt_strcmp("led0", argv[1]))
         {
             led = led0;
         }
         else
         {
             led = led1;
         }

         if (!rt_strcmp("0", argv[2]))
         {
             loop = LOOP_PERMANENT;
         }
         else
         {
             loop = (uint8_t)atoi(argv[2]);
         }

         mode = (uint8_t)atoi(argv[3]);
         if (mode > sizeof(led_blink_mode) / sizeof(led_blink_mode))
         {
             mode = 0;
         }
         led_set_mode(led, loop, led_blink_mode[mode]);
         led_start(led);
     }
     else
     {
         rt_kprintf("led_switch {led} {loop} {mode}\r\n");
         rt_kprintf("mode:\r\n");
         rt_kprintf("0->1Hz\r\n");
         rt_kprintf("1->10Hz\r\n");
         rt_kprintf("2->light on\r\n");
         rt_kprintf("3->light off\r\n");
         rt_kprintf("4->Non-fixed freq1\r\n");
         rt_kprintf("5->Non-fixed freq1\r\n");
         rt_kprintf("for example:\r\n");
         rt_kprintf("led_switch led0 10 3\r\n");
     }
}
MSH_CMD_EXPORT(led_switch, change led mode);
可以了,但是,这里我使用自动初始化,线程是运行了,但是led没有闪烁。以导出msh命令的方式,led运行正常;猜测是采用INIT_APP_EXPORT时,其他初始化对led做过手脚;
原因:
  • 多个app 函数在  SECTION(".rti_fn."level)(其中 APP_EXPORT --> 6)段中的顺序依赖于编译器;
  • 这个bsp 很多部分不依赖于自动初始化,大部分的初始化放在 main 函数中;

signalLed 的心跳线程初始化放在 mian 函数末尾,搞定;
总结
解决麻雀无法使用menuconfig 总的来说很简单,比较初始的rtconfig.h 和 通过 menuconfig 生成的 rtconfig.h, 通过1.勾选,2.编写KConfig文件,3.增加config项(对应上述解决方案),使二者内容一致即可。
其实,这个bsp不用增加额外的包,也可以在其上开发很棒的应用,所以解决不解决这个对后续开发没有任何影响,只是生命不熄, 折腾不止;

使用特权

评论回复
5
鱼柯1412|  楼主 | 2020-6-19 09:34 | 只看该作者
[开发板]麻雀1号-04_connect onenet

使用特权

评论回复
6
鱼柯1412|  楼主 | 2020-7-1 17:15 | 只看该作者
[开发板]麻雀1号-04_项目文档
视频  https://www.bilibili.com/video/BV1bz4y1X7Di/



RT-Thread作品秀】远程可配置数据采集节点.pdf

1018.06 KB

使用特权

评论回复
7
pengxiang01| | 2022-2-6 09:04 | 只看该作者
你好,可以看下auto_link_wifi 怎么写的吗?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

6

帖子

0

粉丝