很久没有记笔记了。今天要记点东西,不然以后又忘记了。

随着时代的发展,现在的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 (无线升级功能)的尴尬笔记的更多相关文章

  1. 5、CC2541芯片中级教程-OSAL操作系统(PWM+看门狗)

    本文根据一周CC2541笔记汇总得来—— 适合概览和知识快速索引—— 全部链接: 中级教程-OSAL操作系统\OSAL操作系统-实验01 OSAL初探 [插入]SourceInsight-工程建立方法 ...

  2. linux设备驱动归纳总结(十一):写个简单的看门狗驱动【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-112879.html linux设备驱动归纳总结(十一):写个简单的看门狗驱动 xxxxxxxxxxx ...

  3. RM-Linux驱动--Watch Dog Timer(看门狗)驱动分析

    from:http://blog.csdn.net/geekcome/article/details/6595265 硬件平台:FL2440 内核版本:2.6.28 主机平台:Ubuntu 11,04 ...

  4. tiny4412 裸机程序 三、关闭看门狗和调用C程序【转】

    本文转载自:http://blog.csdn.net/eshing/article/details/37112779 一.原理说明 上是章中大家可能有会觉得奇怪,CPU不是有看门狗嘛?为什么CPU没有 ...

  5. 【Linux开发】linux设备驱动归纳总结(十一):写个简单的看门狗驱动

    linux设备驱动归纳总结(十一):写个简单的看门狗驱动 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  6. Spring Boot 实现看门狗功能 (调用 Shell 脚本)

    需要实现看门狗功能,定时检测另外一个程序是否在运行,使用 crontab 仅可以实现检测程序是否正在运行,无法做到扩展,如:手动重启.程序升级(如果只需要实现自动升级功能可以使用 inotify)等功 ...

  7. STM32之看门狗(独立与窗口)

    广大的互联网网友们,大家早上中午晚上好,我是某某某..对于狗..看过<忠犬八公>的我.无不深深的被狗的义气与灵气所震撼..我也觉得在所有mcu中用看门狗来形容让系统复位的功能是很恰当的.也 ...

  8. zigbee学习之路(十一):看门狗

    一.前言 今天,我们要通过实验学习和认识一下看门狗的使用,看门狗是为了防止防止程序跑飞的,通过不断的喂狗,使看门狗能持续监管程序的运行状态,当程序跑飞时,能及时把程序拽回来. 二.原理与分析 在CPU ...

  9. STM32之独立看门狗与窗口看门狗总结

    一.独立看门狗 STM32 的独立看门狗由内部专门的 40Khz 低速时钟驱动,即使主时钟发生故障,它也仍然有效. 看门狗的原理:单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路 ...

随机推荐

  1. __attribute__((format(printf, a, b)))

    最近,在看libevent源码,第一次看到__attribute__((format(printf, a, b)))这种写法.因此,在这里记录下用法. 功能:__attribute__ format属 ...

  2. Luogu P2727 【01串 Stringsobits】

    看到题解里好像都是用$DP$解决的,本着禁止DP的原则,我来提供一发纯数学其实和DP本质相同的题解,前两天刚反演题,脑子炸了,本来说换换脑子,结果还是数学 首先受进制思想启发,我们不妨按位考虑,考虑这 ...

  3. .NET Standard和.NET Core是什么关系(转载)

    .NET Standard vs .NET Core 问: I have read about the difference between .NET Standard and .NET Core, ...

  4. Linux之《荒岛余生》(三)内存篇

    原文:https://juejin.im/post/5c00aee06fb9a049be5d3641 小公司请求量小,但喜欢滥用内存,开一堆线程,大把大把往jvm塞对象,最终问题是内存溢出. 大公司并 ...

  5. Python学习笔记之try-except

    Python使用被称为异常的特殊对象来管理程序执行期间发生的错误.每当发生让Python不知所措的错误时,它都会创建一个异常对象.如果你编写了处理该异常的代码,程序将继续运行:如果你未对异常进行处理, ...

  6. 2019 淘友天下java面试笔试题 (含面试题解析)

      本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.淘友天下等公司offer,岗位是Java后端开发,因为发展原因最终选择去了淘友天下,入职一年时间了,也成为了面 ...

  7. es6中的arrowfunction

    es6新增箭头函数,主要解决了以下几点问题 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象. 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误. 不可以使用 ...

  8. error LNK2019: 无法解析的外部符号 _main,该符号在函数 ___tmainCRTStartup 中被引用

    出现如下错误: error LNK2019: 无法解析的外部符号 _main,该符号在函数 ___tmainCRTStartup 中被引用 解决办法:

  9. linux 下按照文件名模糊查找文件

    fnmatch int fnmatch(const char *pattern, const char *string, int flags); 参数说明 FNM_NOESCAPE 如果这个标志设置了 ...

  10. 使用fio命令查看磁盘iops

    具体命令: fio -filename=./localhost.2019-05-08.log -direct=1 -iodepth 1 -thread -rw=randrw -ioengine=psy ...