蓝牙nrf51822空中升级

来源:互联网 发布:三益钢琴js 600na图片 编辑:程序博客网 时间:2024/04/29 23:02
原理简介:
对于单片机做的产品,要实现在线升级,单片机内部一般是两段代码,一个是bootloader程序,一个是用户app程序,bootloader程序主要就是实现app升级的程序,它是单片机上电后首次运行的程序,app程序就是实现产品功能的程序。
对于nRF51822来说,稍微有点特殊,但是本质原理也是一样的,nRF51822芯片内部有段SoftDevice的程序,它是芯片上电后首次运行的程序,不过这段程序不负责程序升级,它是Nordic官方提供的蓝牙协议栈程序,当然它也具备一点bootloader的功能,也就是说,芯片上电后,它会判断芯片内部是否有bootloader代码(bootloader代码位置固定,所以它能判断出是否有合法的bootloader程序),若有bootloader程序则会跳转到bootloader程序执行,若没有bootloader程序而只检测到了用户的app程序,那么就直接跳转到app程序运行,当然这个bootloader程序是我们自己写的代码,只是它存储的位置和app程序是不一样的。
bootloader程序差不多也只做两件事情,1:控制程序的跳转,比如跳转到app程序;2:实现app程序升级;
当然bootloader是我们自己写的,你要实现更多的功能也是可以的,但是最基本的功能就是这两个,bootloader运行后,检测直接跳转到app的条件是否满足(app程序合法,相关标志位合法),若满足就直接跳转到app执行app程序,若不满足就继续执行bootloader,等待升级的相关操作命令;
 
手机端DFU功能简介:
单片机段程序准备好了,当然就需要手机端程序来实现固件的升级了,主要工作流程如下:
1,扫描蓝牙设备,连接蓝牙设备,查询蓝牙设备是否支持DFU服务;
2,若支持DFU服务,那么将本地的固件通过蓝牙发送出去;

3,数据发送完毕,升级固件成功




nRF51822程序加载顺序

1)SoftDevice加载;

2)SoftDevice初始化蓝牙协议栈;

3)SoftDevice检查0x10001014处是否保存有有效的BootLoader地址, 如果不是跳转到0x14000处的APP执行,流程结束.

4)SoftDevice跳转到BootLoader

5)BootLoader进行他的业务处理工作;

6)BootLoader跳转到0x14000处的APP执行,流程结束.



下面介绍百度手环的成个代码关于OTA的工作流程
1:SoftDevice加载;

2:SoftDevice初始化蓝牙协议栈;

3:我们已经有 Bootloader了所以他检查Bootloader是不是合理

代码: APP_ERROR_CHECK_BOOL(NRF_UICR->CLENR0 == CODE_REGION_1_START);//检测BOOTLOADER是否存在

4:检查Bootloader标志位if (should_enter_bootloader || (wdt_reset & 0x02))

if进入OTA模式 err_code = bootloader_dfu_start();//进入OTA里面完成:蓝牙连接,BIN传到WSAP.

等待完成进入。

然后进入APP(是否设置标志位都进入

       //跳到DFU_BANK_0_REGION_START(0x00014000 application程序存放的首地址跳过去就不会往下运行了

       bootloader_app_start(DFU_BANK_0_REGION_START);

5:进入APP后如果设置标志位,然后复位循环以上的。

注意:Bootloader和Application还有SoftDevice是三个独立的代码,
其中SoftDevice是官方提供的HEX文件,(S110、S120或者S130等蓝牙协议)不可修改。

代码分析

这时Application工程中的触发OTA模式

/**********************************************************************

* User to reset the MCU & enter OTA

***********************************************************************/

void trigger_ota_mode(void)

{

 

   sd_power_gpregret_set(0x01);//设置一个保留的寄存器为0X01(作为启动OTA的标志)

   //reset the system and start OTA

   NVIC_SystemReset();//复位进入OTA

}


然后再BOOTLOADER里判断标志位。

uint8_t should_enter_bootloader =  NRF_POWER->GPREGRET & 0xff;

   uint16_t wdt_reset = (NRF_POWER->RESETREAS) & (0xFFFF);

   

   if (should_enter_bootloader || (wdt_reset & 0x02))

满足进入OTA,不满足跳转Application。

简单的说就是:

设置标志位》判断》进入》运行》跳转到APP。

下面是BOOTLOAER   mian完整代码


int main(void)

{

   uint32_t err_code;

   

   wdt_stop(); //stop wdt whether it started or not  

   leds_init();


   // This check ensures that the defined fields in the bootloader corresponds with actual

   // setting in the nRF51 chip.

   APP_ERROR_CHECK_BOOL(NRF_UICR->CLENR0 == CODE_REGION_1_START);//检测BOOTLOADER是否存在

   //检查BOOTLOADER的地址是不是0X03C800

   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();

   //进入  OTA的条件, application程序中  sd_power_gpregret_set(0x01);就是设置这个 NRF_POWER->GPREGRET

   uint8_t should_enter_bootloader =  NRF_POWER->GPREGRET & 0xff;

   uint16_t wdt_reset = (NRF_POWER->RESETREAS) & (0xFFFF);

   

   if (should_enter_bootloader || (wdt_reset & 0x02))

   {

       nrf_gpio_pin_set(LED1);

       // Initiate an update of the firmware.

       err_code = bootloader_dfu_start();//进入OTA里面完成:蓝牙连接,BIN传到WSAP.

       APP_ERROR_CHECK(err_code);


       nrf_gpio_pin_clear(LED1);

   }


   //exit from DFU unit so just Start application

//进入OTA条件不满足进入application

   {

       //set retain register

       NRF_POWER->GPREGRET = 0x00;//清0

       //clear AIRCR register

       NRF_POWER->RESETREAS = 0x04;


       if(wdt_reset & 0x02) {

          NRF_POWER->RESETREAS = 0x02;

       }


       // Select a bank region to use as application region.

       // @note: Only applications running from DFU_BANK_0_REGION_START is supported.

       //跳到DFU_BANK_0_REGION_START(0x00014000 application程序存放的首地址跳过去就不会往下运行了

       bootloader_app_start(DFU_BANK_0_REGION_START);

       

   }

   leds_off();

   

   //comes here should reenter DFU

   //这里重新进入OTA应该是如果bootloader_app_start(DFU_BANK_0_REGION_START);失败

   NRF_POWER->GPREGRET = 0x01;

   

   NVIC_SystemReset();//复位重新进入OTA因为NRF_POWER->GPREGRET = 0x01;

}


1 0
原创粉丝点击