crazyflie2_nrf51822程序分析--MBS

从之前对总体结构的介绍,参考crazyflie2_nrf51822程序分析--总体结构

可以看出来程序运行的顺序是MBR->MBS->Bootloader->Firmware,MBR我们动不了,所以先分析下MBS都做了什么事情,main函数主要做的事情如下:

<span style="font-size:14px;">int main() __attribute__ ((noreturn));
int main()
{
  press = press_none;

  /* Lock flash for MBR and MBS
  锁住MBR and MBS */
  NRF_MPU->PROTENSET0 = 0x00000001UL;
  NRF_MPU->PROTENSET1 = 0x80000000UL;

  //LED设置为输出模式
  nrf_gpio_cfg_output(LED_PIN);
  nrf_gpio_pin_set(LED_PIN);
  //控制STM32的供电引脚拉低,禁止对stm32供电
  nrf_gpio_cfg_output(PM_VCCEN_PIN);
  nrf_gpio_pin_clear(PM_VCCEN_PIN);
  //按键引脚配置为输入上拉
  nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP);
  //选择晶振源:HFCLK,就是外部晶振
  NRF_CLOCK->TASKS_HFCLKSTART = 1UL;
  while(!NRF_CLOCK->EVENTS_HFCLKSTARTED);

  // Start button timer 开启检测按键定时器,通过比较器判断按下的时间长短
  NRF_TIMER0->PRESCALER = 7;   // Prescaler of 16, result frequency is 1MHz
  NRF_TIMER0->BITMODE = TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos;
  NRF_TIMER0->CC[0] = 1.5*SEC;   // Launch bootloader long press timing
  NRF_TIMER0->EVENTS_COMPARE[0] = 0;
  NRF_TIMER0->CC[1] = 5*SEC;   // Launch bootloader verylong press timing
  NRF_TIMER0->EVENTS_COMPARE[1] = 0;
  NRF_TIMER0->TASKS_CLEAR = 1;
  NRF_TIMER0->TASKS_START = 1;

  // Setup LED blinking timer开启灯闪烁定时器
  NRF_TIMER1->PRESCALER = 7;  //Prescaler of 16, result frequency is 1MHz
  NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos;
  NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk;

  // Calculate number of page before the bootloader计算页的个数
  if ((*(uint32_t*)(BOOTLOADER_CONFIG)) > (FLASH_SIZE*PAGE_SIZE))
    fault();
  flashPages = (*(uint32_t*)(BOOTLOADER_CONFIG))/1024;

  if (nrf_gpio_pin_read(BUTTON_PIN) == 0) {
    press = press_short;
  }

  //判断按下按键的时间,按下时间越长,灯闪越快
  while (nrf_gpio_pin_read(BUTTON_PIN) == 0) {
  // LED定时器
    if (NRF_TIMER1->EVENTS_COMPARE[0]) {
      NRF_TIMER1->EVENTS_COMPARE[0] = 0;
      nrf_gpio_pin_toggle(LED_PIN);
    }
    // 1.5s长按定时器
    if (NRF_TIMER0->EVENTS_COMPARE[0]) {
      NRF_TIMER0->EVENTS_COMPARE[0] = 0;
      blinking_timer(1*SEC);
      press = press_long;
    }
    // 5s长按定时器
    if (NRF_TIMER0->EVENTS_COMPARE[1]) {
      NRF_TIMER0->EVENTS_COMPARE[1] = 0;
      blinking_timer(250*MS);
      NRF_TIMER0->TASKS_STOP = 1UL;
      press = press_verylong;
    }
  }

  // Saves the detected press in a retained register
  //保留按键按压状态在retain寄存器中,Bootloader中会获取GPREGRET来判断按键时间长短
  NRF_POWER->GPREGRET &= ~(0x03UL << 1);
  NRF_POWER->GPREGRET |= 0x80 | ((press&0x03UL)<<1);</span>

  //通过判断按键按下时间长短,进入不同的模式
  if (press != press_verylong) {
    if(verify_flash_flags()) {
      //fault();
      copy_flash();//这里在做什么事情?需要进一步看code,论坛中有点对这块的解释,但是没明白这里真正的作用是什么?</span>
    } else {
      start_firmware();//这里是进入bootloader
    }
  } else {
    start_stm_dfu();//very long 按下会进入使得stm进入dfu
  }

  while(1);
}

大致就是在判断按键按压的时间长短,然后进入不同模式,但是对于上面红色部分flash的一些操作,不知道在做什么事情,论坛中有一些解释,但是还是不太懂,论坛链接如下:

https://forum.bitcraze.io/viewtopic.php?f=6&t=1640

顺便贴出解释的内容:

问题:Crazyflie
bootloader sequence

Hi. I‘m trying to analyze bootloader sequence.

I‘m starting with mbs program.

In main function, the program detects button input command,

and if the button is not "very_long", it calls verify_flash_flags(), line 242 of mbs/main.c

In the function, it uses variable "flashFlags", which is a pointer for last flash page.

CopyFlashFlags_t *flashFlags = (void*)FLASH_BASE+((flashPages-1)*PAGE_SIZE);

Variable "flashPages" is caculated before, using bootloader address written in NRF_UICR_BASE+0x80

I stucked here, I can not find who write the flash page that "flashFlags" read.

It contains header; size of bootloader and softdevice; crcs; etc.

Please help me where the flash page is written.

arnaud回答:

Hi,

The bootloader is described in the wiki there: https://wiki.bitcraze.io/doc:crazyflie:
... r:protocol
 and is implemented in crazyflie2-nrf-bootloader.

The MBS you are looking at is not the main bootloader but it can flash the bootloader
and the softdevice. The idea is that the bootloader is not able to write over itself and over the bluetooth softdevice (the bootloader depends of the softdevice). So the solution is to flash a new bootloader and a new softdevice in a pre-defined way: anywhere
in the writable flash, with a correct CRC32 checksum and with the address in a well-known location. This way when the copter restart the MBS verifies the checksum and if it matches it flashes softdevice and bootloader. From the MBS point of view the data appear
here like magic .

This design tries to avoid any possibility to brick the bootloader from the bootloader:
in order to change the bootloader you must do it on purpose, not by mistake.

The real bootloader (the one that permits to load the flash from radio) is in this project: https://github.com/bitcraze/crazyflie2-nrf-bootloader

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-13 18:53:04

crazyflie2_nrf51822程序分析--MBS的相关文章

crazyflie2_nrf51822程序分析--总体结构

为了尊重原始版本,将英文原文贴出来,同时将一些需要注意的地方加上我的注释 Source code of the firmware running in the Crazyflie 2.0 nRF51822. This microcontroller have a couple of roles: Power management (ON/OFF logic and battery handling),功耗管理,打开/关闭stm32 Radio communication 无线通信 Enhance

基于时间片轮转程序分析进程调度

张雨梅   原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-10000 背景知识 一般程序运行过程中都会发生中断,发生中断时,CPU先把当前的内容保存,然后执行中断程序,中断返回时,根据保存的内容恢复现场.这次实验用一个简单的时间片轮转程序分析进程调度的过程. 实验过程 使用实验楼的虚拟机操作,实验代码在mykernel中找,包括3个c文件,mypcb.h,mymain.c,myinterrupt.c. 打开

linux程序分析工具介绍(一)—-”/proc”

写在最前面:在开始本文之前,笔者认为先有必要介绍一下linux下的man,如果读者手头用linux系统,直接在终端输入man man便可以看到详细的说明,我在这里简单的总结一下,man命令是用来查看linux下各种命令.工具等的用户手册(manual)的.一种比较常用的用法是"man n field",这里的n是要查找的手册了类型,field是关键字.在这里介绍一下n: 0 /usr/include下的头文件 1 可执行程序和shell命令 2 系统调用 3 系统库函数 4 /dev下

(IOS)BaiduFM 程序分析

本文主要分享下楼主在学习Swift编程过程中,对GitHub上的一个开源app BaiduFM的研究心得. 项目地址:https://github.com/belm/BaiduFM-Swift 一.项目简介 项目通过使用百度音乐的API实现了播放.下载与收藏音乐的FM基本功能.同时实现了歌词滚动,显示实时进度条,支持后台播放,锁屏显示歌曲信息及控制播放等附加功能并添加了对Apple Watch的支持.此APP可谓是功能十分强劲,下面楼主就来好好分析下这款APP的代码及功能实现原理. 二.APP

Hadoop之MapReduce程序分析

摘要:Hadoop之MapReduce程序包括三个部分:Mapper,Reducer和作业执行.本文介绍和分析MapReduce程序三部分结构. 关键词:MapReduce   Mapper  Reducer   作业执行 MapReduce程序包括三个部分,分别是Mapper,Reducer和作业执行. Mapper 一个类要充当Mapper需要继承MapReduceBase并实现Mapper接口. Mapper接口负责数据处理阶段.它采用形式为Mapper<K1,V1,K2,V2>的Jav

linux程序分析工具介绍(三)——sar

本文要介绍的sar,是linux下用来分析系统本身运行情况的非常有用的工具.我们知道,程序在操作系统上要运行,要关注的点不外乎内存,CPU和IO(包括磁盘IO和网络IO).我们的应用程序在操作系统中运行前,我们需要了解系统当前的内存,cpu和IO的使用状况,还需要明白我们的应用程序运行时自身所需要的内存,cpu和IO资源的情况.只有操作系统剩余的内存,cpu和IO资源能够满足应用程序所需要的,才能保证应用程序在操作系统中正常的运行.sar就是用来帮助我们了解操作系统当前内存,cpu和IO等资源的

linux程序分析工具介绍(二)—-ldd,nm

本文要介绍的ldd和nm是linux下,两个用来分析程序很实用的工具.ldd是用来分析程序运行时需要依赖的动态库的工具:nm是用来查看指定程序中的符号表相关内容的工具.下面通过例子,分别来介绍一下这两个工具: 1. ldd, 先看下面的例子, 用ldd查看cs程序所依赖的动态库: [email protected]:~/Public$ ldd cs linux-gate.so.1 => (0xffffe000) libz.so.1 => /lib/libz.so.1 (0xb7f8c000)

代码实现:判断101-200之间有多少个素数(质数),并输出所有素数。 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数。

package com.heima.Coding; /* 判断101-200之间有多少个素数(质数),并输出所有素数. 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数.*/ public class Test { public static void main(String[] args) { int count = 0; for (int i = 100; i < 200; i++) { for (int j = 2; j <=

C#程序分析

一.程序及问题 阅读下面程序,请回答如下问题: 问题1:这个程序要找的是符合什么条件的数? 问题2:这样的数存在么?符合这一条件的最小的数是什么? 问题3:在电脑上运行这一程序,你估计多长时间才能输出第一个结果?时间精确到分钟(电脑:单核CPU 4.0G Hz,内存和硬盘等资源充足). 问题4:在多核电脑上如何提高这一程序的运行效率? using System; using System.Collections.Generic; using System.Text; namespace Find