nRF51822 看门狗和OTA (无线升级功能)的尴尬笔记
很久没有记笔记了。今天要记点东西,不然以后又忘记了。
随着时代的发展,现在的SDK已经是13.0了。蓝牙5.0也就来了。废话就少说了,记笔记吧。
两年前搞过nRF51822 的无线升级功能,那时候用的还是 SDK5.20,直接用hex镜像进行升级的。后来的SDK就不再是hex,要用zip了,现在还不清楚具体做APP时候的用法。以后再说,先用官方提供了nRF_ToolBox能升级就很不错了。
现在用了新的SDK,试了很长一段时间,各种各样的文档都过了,各种各样的方法都试过了,就是不行,真特么尴尬。后来今天又试了,到官方论坛去搜各种各样的情况,尝试,到底还是有点眉目了。
SDK9.0的DFU例子,在..\nRF51_SDK_9.0.0_2e23562\examples\dfu\bootloader\pca10028\dual_bank_ble_s110 这个路径,我修改了一点点程序,
1.修改 bootloader_settings.c 文件下的这一行
uint8_t m_boot_settings[CODE_PAGE_SIZE] __attribute__((at(BOOTLOADER_SETTINGS_ADDRESS))) __attribute__((used))
为
uint8_t m_boot_settings[CODE_PAGE_SIZE] __attribute__((at(BOOTLOADER_SETTINGS_ADDRESS))) __attribute__((used)) = {BANK_VALID_APP};
没有这个,程序用一些手段烧进去了它就一直是bootloader那运行,进不了application,具体的原因查看下下面的这个链接,官方论坛网友提的一个问题和别人的解答:
https://devzone.nordicsemi.com/question/2304/device-is-always-in-bootloader-mode/
2.修改main函数:
int main(void)
{
uint32_t err_code; // bool dfu_start = false;
bool app_reset = (NRF_POWER->GPREGRET == BOOTLOADER_DFU_START); #ifdef UART_DEBUG
uart_init();
M_LOG("\r\n[Boot]Uart Init OK.\r\n");
#endif if (app_reset)
{
M_LOG("[Boot]in DFU Mode...\r\n");
NRF_POWER->GPREGRET = ;
} // leds_init(); // This check ensures that the defined fields in the bootloader corresponds with actual
// setting in the nRF51 chip.
APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START);
APP_ERROR_CHECK_BOOL(NRF_FICR->CODEPAGESIZE == CODE_PAGE_SIZE); // Initialize.
timers_init(); err_code = app_timer_create( &feed_wd_timer_id, APP_TIMER_MODE_REPEATED, timer_index_feed_wd );
APP_ERROR_CHECK(err_code); #if 0
buttons_init();
#endif (void)bootloader_init();
#if 0
if (bootloader_dfu_sd_in_progress())
{
// nrf_gpio_pin_clear(UPDATE_IN_PROGRESS_LED); err_code = bootloader_dfu_sd_update_continue();
APP_ERROR_CHECK(err_code); ble_stack_init(!app_reset);
scheduler_init(); err_code = bootloader_dfu_sd_update_finalize();
APP_ERROR_CHECK(err_code); // nrf_gpio_pin_set(UPDATE_IN_PROGRESS_LED);
}
else
#endif
{
// If stack is present then continue initialization of bootloader.
ble_stack_init(true);//!app_reset);//
scheduler_init();
M_LOG("[Boot]ble_stack_init OK...\r\n"); }
#if 0
dfu_start = app_reset;
dfu_start |= ((nrf_gpio_pin_read(BOOTLOADER_BUTTON) == ) ? true: false); if (dfu_start || (!bootloader_app_is_valid(DFU_BANK_0_REGION_START)))
#else
if(app_reset)
#endif
{
// nrf_gpio_pin_clear(UPDATE_IN_PROGRESS_LED); err_code = app_timer_start(feed_wd_timer_id, APP_TIMER_TICKS(,APP_TIMER_PRESCALER), NULL);
APP_ERROR_CHECK(err_code); // Initiate an update of the firmware.
err_code = bootloader_dfu_start();
APP_ERROR_CHECK(err_code); // nrf_gpio_pin_set(UPDATE_IN_PROGRESS_LED);
} if (bootloader_app_is_valid(DFU_BANK_0_REGION_START) && !bootloader_dfu_sd_in_progress())
{ (void)app_timer_stop( feed_wd_timer_id );
M_LOG("[Boot]bootloader_app_start...\r\n");
// Select a bank region to use as application region.
// @note: Only applications running from DFU_BANK_0_REGION_START is supported.
bootloader_app_start(DFU_BANK_0_REGION_START);
}
NVIC_SystemReset();
}
err_code = app_timer_create( &feed_wd_timer_id, APP_TIMER_MODE_REPEATED, timer_index_feed_wd );
APP_ERROR_CHECK(err_code);
err_code = app_timer_start(feed_wd_timer_id, APP_TIMER_TICKS(,APP_TIMER_PRESCALER), NULL);
APP_ERROR_CHECK(err_code);
(void)app_timer_stop( feed_wd_timer_id );
这个定时器就是解决今天尴尬的关键!
3.话说当 application 触发进入 OTA 模式很简单,只需要在加入以下代码即可:
void ota_mode_entry(void)
{
sd_softdevice_disable();
NRF_POWER->GPREGRET = 0xB1;
sd_softdevice_enable(NRF_CLOCK_LFCLKSRC_RC_250_PPM_8000MS_CALIBRATION,NULL);
NVIC_SystemReset();
}
但是,但是!!!!蛋蛋是!!!
如果你的 application 启动了 看门狗, 当软件复位的时候,看门狗是不会停止的,它还在工作,当你不喂它,很显然它就狂吠你,导致重启。
这时候重启很显然就没办法再进行升级了,而是又进入了application。
nRF51822 的看门狗很奇怪,它一旦起来了,就不能软件关闭了,而且调用NVIC_SystemReset() 不会致使它的寄存器清除,它还在跑。
解决的办法只能是在 bootloader 程序加喂狗程序咯。论坛上有人直接在 for(;;)循环里面加喂狗代码,但是并不十分管用,因为有个低功耗休眠函数会阻塞程序,导致喂不到狗,
不知道论坛上的那些大神是怎么想的,我也懒得去研究他们的办法和解释,
所以只能加个软件定时器,1秒喂一次,就当是把它关闭了吧。下面是这个软件定时器的回调:
static app_timer_id_t feed_wd_timer_id; static void timer_index_feed_wd( void *p_context )
{
//feed the dog
NRF_WDT->RR[] = WDT_RR_RR_Reload;
}
记得还要吧timers_init()里的第二个参数调整加1
#define APP_TIMER_MAX_TIMERS 4// 3
OK了,蛋蛋疼的OTA和看门狗之间的尴尬就化解了。
其他打包 zip 和烧录的 工作,就交给 帮助文档吧。
速度搜索一下 你的电脑,找到 How to generate the INIT file for DFU.pdf 文档。
用到的工具是: 1.hex2bin.exe 2.nrfutil.exe
下面是命令行脚本的内容,这样就可以生成 zip 了。
.\hex2bin.exe app.hex
.\nrfutil.exe dfu genpkg app.zip --application app.bin --application-version 0xffffffff --dev-revision 0xffff --dev-type 0xffff --sd-req 0x0064
nRF51822 看门狗和OTA (无线升级功能)的尴尬笔记的更多相关文章
- 5、CC2541芯片中级教程-OSAL操作系统(PWM+看门狗)
本文根据一周CC2541笔记汇总得来—— 适合概览和知识快速索引—— 全部链接: 中级教程-OSAL操作系统\OSAL操作系统-实验01 OSAL初探 [插入]SourceInsight-工程建立方法 ...
- linux设备驱动归纳总结(十一):写个简单的看门狗驱动【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-112879.html linux设备驱动归纳总结(十一):写个简单的看门狗驱动 xxxxxxxxxxx ...
- RM-Linux驱动--Watch Dog Timer(看门狗)驱动分析
from:http://blog.csdn.net/geekcome/article/details/6595265 硬件平台:FL2440 内核版本:2.6.28 主机平台:Ubuntu 11,04 ...
- tiny4412 裸机程序 三、关闭看门狗和调用C程序【转】
本文转载自:http://blog.csdn.net/eshing/article/details/37112779 一.原理说明 上是章中大家可能有会觉得奇怪,CPU不是有看门狗嘛?为什么CPU没有 ...
- 【Linux开发】linux设备驱动归纳总结(十一):写个简单的看门狗驱动
linux设备驱动归纳总结(十一):写个简单的看门狗驱动 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
- Spring Boot 实现看门狗功能 (调用 Shell 脚本)
需要实现看门狗功能,定时检测另外一个程序是否在运行,使用 crontab 仅可以实现检测程序是否正在运行,无法做到扩展,如:手动重启.程序升级(如果只需要实现自动升级功能可以使用 inotify)等功 ...
- STM32之看门狗(独立与窗口)
广大的互联网网友们,大家早上中午晚上好,我是某某某..对于狗..看过<忠犬八公>的我.无不深深的被狗的义气与灵气所震撼..我也觉得在所有mcu中用看门狗来形容让系统复位的功能是很恰当的.也 ...
- zigbee学习之路(十一):看门狗
一.前言 今天,我们要通过实验学习和认识一下看门狗的使用,看门狗是为了防止防止程序跑飞的,通过不断的喂狗,使看门狗能持续监管程序的运行状态,当程序跑飞时,能及时把程序拽回来. 二.原理与分析 在CPU ...
- STM32之独立看门狗与窗口看门狗总结
一.独立看门狗 STM32 的独立看门狗由内部专门的 40Khz 低速时钟驱动,即使主时钟发生故障,它也仍然有效. 看门狗的原理:单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路 ...
随机推荐
- Xamarin vs React Native vs Ionic vs NativeScript: Cross-platform Mobile Frameworks Comparison
CONTENTS Reading time: 14 minutes Cross-platform mobile development has long been a viable alternati ...
- golang学习笔记 go 相关命令
go build 命令一些可选项的用途和用法 在运行go build命令的时候,默认不会编译目标代码包所依赖的那些代码包.当然,如果被依赖的代码包的归档文件(*.a)不存在,或者源码文件有了变化,那么 ...
- mini Redis(项目 二)
一个仿Redis的内存数据库(主要用来做命令解析)服务端, 客户端使用的开源工具 : https://dom4j.github.io/ github:https://github.com/h ...
- 对Haskell这门语言的基本认识
Haskell语言的核心特征: 1. 函数式,而且是纯函数式(purely functional) 首先,引用一下维基百科上对“典型的函数式编程语言”的划分: 一: 纯函数式 1. 强静态类型: Mi ...
- pom.xml管理jar包——安全性框架配置文件
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> &l ...
- C++中Matrix(矩阵)的基本运算( +、-、=、<<)
利用二维指针开辟空间形成二维数组: 原题为设计一个Matrix类,实现基本的矩阵运算: 初次设计为HL[10][10]数组,存放矩阵元素,后改为二维指针: 主要问题存在于二维指针理解的不透彻,无法理解 ...
- SpringJDBC源码解析
读完本篇文章需要很长很长时间.... 传统JDBC 相信大家对传统的jdbc已经很熟悉了,无非就是下面这个流程 1234567891011 //1.加载驱动程序Class.forName(" ...
- 使用Git Bash向GitHub上传本地项目
第一步:下载Git Bash(https://gitforwindows.org/),安装的过程是一路下一步,就不细说啦: 第二步:打开Git Bash,如下图显示: 第三步:现在让我们先放一放Git ...
- c# 根据域名的到对应的IP
今天做了域名解析,由于项目里要用到域名对应的ip 所以做了这个小程序 private void button_Net_Click(object sender, EventArgs e) ...
- cs1.6 人物地址查询
打开游戏 控制台命令 增加一个BOT:bot_add 增加一个警察:bot_add_ct 增加一个匪徒:bot_add_t 让BOT站在原地不动:bot_stop 1 "-"减号: ...