2020年6月11日星期四

痞子衡嵌入式:链接函数到8字节对齐地址或可进一步提升i.MXRT内核执行性能

痞子衡嵌入式:链接函数到8字节对齐地址或可进一步提升i.MXRT内核执行性能


一个有趣的结论,Cortex-M7上将函数链接到8字节对齐的地址有利于指令双发射,这就是进一步提升代码执行性能的秘密

  大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是i.MXRT上进一步提升代码执行性能的经验

  今天跟大家聊的这个话题还是跟痞子衡最近这段时间参与的一个基于i.MXRT1170的大项目有关,痞子衡在做其中的开机动画功能,之前写过一篇文章 《降低刷新率是定位LCD花屏显示问题的第一大法》 介绍了开机动画功能的实现以及LCD显示注意事项,在此功能上,痞子衡想进一步测试从芯片上电到LCD屏显示第一幅完整图像的时间,这个时间我们暂且称为1st UI时间,该时间的长短对项目有重要意义。

  痞子衡分别测试了代码在XIP执行下和在TCM里执行下的1st UI时间,得到的结果竟然是XIP执行比TCM执行还要快50ms,这是怎么回事?这完全颠覆了我们的理解,i.MXRT上TCM是与内核同频的,Flash速度远低于TCM。如果是XIP执行,即使有I-Cache加速,也最多与TCM执行一样快,怎么可能做到比TCM执行快这么多。于是痞子衡便开始深挖这个奇怪的现象,然后发现了进一步提升代码执行性能的秘密。

一、引出计时差异问题

  痞子衡的开机动画程序是基于 \SDK_2.x.x_MIMXRT1170-EVK\boards\evkmimxrt1170\jpeg_examples\sd_jpeg 例程的,只是去了SD卡和libjpeg库相关代码。工程有两个build,一个是TCM里执行(即debug),另一个是XIP执行(即flexspi_nor_debug)。

  项目板上的Flash型号是MX25UW51345G,痞子衡将其配成Octal mode, DDR, 166MHz用于启动。项目板上还有两个LED灯,痞子衡在LED灯上飞了两根线,连同POR引脚一起连上示波器,用于精确测量1st UI各部分时间组成。

  示波器通道1连接POR引脚,表明1st UI时间起点;通道2连接LED1 GPIO,表明ROM启动时间(进入用户APP的时间点);通道3连接LED2 GPIO,做两次电平变化,分别是1st图像帧开始和结束的时间点。翻转LED GPIO代码位置如下:

void light_led(uint32_t ledIdx, uint8_t ledVal);void SystemInit (void) { // 将LED1置1,标示ROM启动时间 light_led(1, 1); SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2)); // ...}void APP_InitDisplay(void){ // ... g_dc.ops->enableLayer(&g_dc, 0); // 将LED2置1,标示1st图像帧开始时间点 light_led(2, 1);}int main(void){ BOARD_ConfigMPU(); BOARD_InitBootPins(); BOARD_BootClockRUN(); BOARD_ResetDisplayMix(); APP_InitDisplay(); while (1)	{	 // ...	}}static void APP_BufferSwitchOffCallback(void *param, void *switchOffBuffer){ s_newFrameShown = true; // 将LED2置0,标示1st图像帧结束时间点 light_led(2, 0);}

  上图是痞子衡抓到的波形(30Hz,XIP),痞子衡一共做了四次测试,分别是30Hz LCD刷新率下的XIP/TCM以及60Hz LCD刷新率下的XIP/TCM,结果如下表所示。表中的Init Time一栏表示的是开机动画程序代码执行时间(从SystemInit()函数开始执行到APP_InitDisplay()函数结束的时间),可以看到TCM执行比XIP执行慢近50ms,这便是奇怪问题所在。

代码位置 LCD刷新率 POR Time Boot Time Init Time Launch Time
XIP 30Hz 3.414ms 10.082ms 34.167ms + 153ms 32.358ms
TCM 30Hz 3.414ms 10.854ms 33.852ms + 203ms 32.384ms
XIP 60Hz 3.414ms 9.972ms 18.142ms + 153ms 16.166ms
TCM 60Hz 3.414ms 10.92ms 17.92ms + 203ms 16.104ms

二、定位计时差异问题

  对于开机动画代码,XIP执行比TCM执行快这个结果,痞子衡是不相信的,于是痞子衡便用二分法逐步查找,发现时间差异是BOARD_InitLcdPanel()函数里的DelayMs()调用引起的,这些人为插入的延时是LCD屏控制器手册里的要求,总延时时间应该是153ms,但是这个函数的执行在XIP下(153ms)和TCM里(203ms)时间不同。

static void BOARD_InitLcdPanel(void){ // ...#if (DEMO_PANEL == DEMO_PANEL_TM103XDKP13) // ... /* Power LCD on */  GPIO_PinWrite(LCD_RESET_GPIO, LCD_RESET_GPIO_PIN, 1); DelayMs(2); GPIO_PinWrite(LCD_RESET_GPIO, LCD_RESET_GPIO_PIN, 0); DelayMs(5); GPIO_PinWrite(LCD_RESET_GPIO, LCD_RESET_GPIO_PIN, 1); DelayMs(6); GPIO_PinWrite(LCD_STBYB_GPIO, LCD_STBYB_GPIO_PIN, 1); DelayMs(140);

没有评论:

发表评论