2043|0

1379

帖子

2

TA的资源

五彩晶圆(初级)

楼主
 

【NXP Rapid IoT评测】Rapid-Iot 启动过程(K64部分)分析 [复制链接]

本帖最后由 cruelfox 于 2019-1-19 14:13 编辑

  NXP Rapid-IoT kit 包含两个MCU, 其中K64是主CPU, 使用在线环境开发的应用程序就是在它上面运行的。通过对下载的源码包进行分析,以及借助GDB对K64执行过程跟踪调试,我大概梳理了一下 K64 MCU 上程序的启动过程。
  首先忽略 Bootloader 部分吧,这部分负责USB连接电脑时的下载功能(参见 https://bbs.eeworld.com.cn/thread-1067400-1-1.html),它先进行一些判断后,再转移到实际的应用程序代码运行。而且如果是自己本地编译工程,SWD下载程序的话, bootloader 也可以去掉不用。
  跟ARM Cortex-m系列其它MCU一样,复位后程序是从 Reset handler 开始执行的。K64 的这部分代码是在 startup_MK64F12.S 这个汇编源文件里面。它先调用 SystemInit(), 处理了 FPU, WDOG 的初试设置,随后执行了简短的操作初始化RAM数据,最终调用 main() 执行。

  main() 函数在 fsl_os_abstraction_free_rtos.c 这个文件里面,从文件名可以推断,Rapid-IoT 的应用是基于 FreeRTOS 开发的。main() 函数本身写得很简单。

  从它调用的函数名称可以推断:先初始化硬件,再创建一个任务 startup_task,最后启动任务调度器,剩余工作就交给 FreeRTOS 管理了。

  BOARD_Init_RPK() 函数在 pin_mux_rpk.c 文件中,它要依次执行一系列的初始化。这个文件居然是 KW41 和 K64 公用的,我把无关的代码在图片上mark了一下

  实际上起作用的只有4行代码,分别是调用
     MK64F_init_hardware()
     MK64F_hardware_init()
     GPIO_PinInit(...)   针对 KW41复位脚状态
     BOARD_InitSPIBusSharing()
  前面这两个函数名……名称看起来是一个意思,却分了两个函数来写。内容都有啥,下面来分析。

  MK64F_init_hardware() 在 hardware_init_MK64F12.c 中,这又是一个很短的函数。

  三个操作的意义从名称和注释已经清晰了。

  MK64F_hardware_init() 在 board.c 文件中,想必就是和具体板子有关的初始化,这个函数写得也不长。

  它调用的函数里面:
  BOARD_InitBootPins() 在 pin_mux.c 中,这个函数长,看起来像软件生成的代码,主要是设置了引脚的功能(对应到哪个片上设备,还是作为 GPIO)
  BOARD_INIT_GPIOS() 在 board.c 中,这个函数中配置了那些作为 GPIO 功能(输入或输出)的引脚,包括输出电平状态。
  BOARD_InitBootClocks() 在 clock_config.c 中,对系统用到的几个时钟源进行配置,决定了CPU, 总线等等的运行频率。(里面CPU运行频率居然设置到了K64最高支持的120MHz, 怪不得成电老虎呀)
  BOARD_InitPeripherals() 也是在 board.c 中,内容稍后分析。
  BOARD_Init_RGB_BLIGHT() 在 peripheral.c 中,对(RGB LED和屏幕背光?)用到的PWM定时器进行初始化。
  BOARD_Init_RPK_LEDS() 在 rpk_led.c 中,是软件层面上的一些初始化。

  BOARD_InitSPIBusSharing() 在 pin_mux_rpk.c 中

  这里面,BOARD_ConfigurePins_RPK_Connectivity() 设置了某4个引脚为GPIO, 然后 BOARD_InitPins_RPK_Connectivity() 设置这4个GPIO的方向和状态;接着,BOARD_ConfigurePins_RPK_SPI_Bus() 配置了另外4个引脚复用功能为 SPI. 为了对这个 SPI 总线上的 Flash 设备(MT25QL128A, 和KW41是共享的)进行访问,需要和KW41协调访问权限。于是用 GPIO 状态与 KW41 进行交互实现互斥。

  再看一下 BOARD_InitPeripherals() 的内容:

  这里初始化了几个片上设备:用于信息输出的 UART, 用于蜂鸣器的定时器,访问 RTC 的 SPI, 另外一个 SPI (SPI 2),用于测量电池电压的16-bit ADC.

  到此,BOARD_Init_RPK() 做的事情就分析完了。接着,FreeRTOS 核心会让 startup_task 这个任务执行,其实这个任务仅仅是调用 app_init.c 中的 main_task(). 要注意到,app_init.c 属于 app_src 目录,意味着它在软件中属于“上层”了。
  这个函数分为两大块,前面是初始化,后面是一个死循环。初始化部分 MEM_Init() 是初始化动态内存管理器(这套代码自己有内存管理,但是和 FreeRTOS 的动态内存管理是什么关系?我还没有去分析),TMR_Init() 是初始化软件定时器(里面会创建一个任务)。最后那句 ATMO_Init() 隐藏了更多的内容。

  在 atmo/core.c 中,ATMO_Init() 函数是这样的:

  以 ATMO_ 开头的代码,属于 Atomsphere 平台的内容,与在线编程环境中看到的那些图形化小模块的关系就紧密了。app_src 目录下面的代码,可以对每个具体项目分别定制,比如删掉不用的部件。
  ATMO_PLATFORM_Init() 这个函数在 atomsphere_platform.c 里面,比较长,包含了软件驱动、显示屏、BLE部分等等的初始化工作。 ATMO_ElementSetup() 会调用在线工程添加的每个“小积木”对应的初始化函数。ATMO_PLATFORM_VariantSetup() 和 ATMO_Setup() 在我创建的工程里面是空的,我暂不确定它们具体用途。ATMO_PLATFORM_PostInit() 与 BLE 和显示界面有关。

  于是到这里,启动过程结束。在 main_task() 最后的循环中,关键的代码是 ATMO_Tick(),  它实现对回调事件的处理,这个函数应当是以固定时间间隔被调用的。
此帖出自RF/无线论坛
点赞 关注
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
快速回复 返回顶部 返回列表