2847|1

1375

帖子

2

TA的资源

五彩晶圆(初级)

楼主
 

【CC1352P测评】ROM代码调用方式分析 [复制链接]

本帖最后由 cruelfox 于 2019-6-23 15:22 编辑

  我在跟踪 nortos (不使用TI RTOS)的工程时发现,在执行到 main() 之前,CPU执行过程中会转到 0x10000000 以后的代码去,显然这已经超出了 flash 的范围,只能是 ROM 中的代码了。那么,C程序是怎样调用ROM中的函数的?

  TI 的工程,Reset handler 入口已经放在编译过的库里面了(SDK的 kernel/nortos/lib/nortos_cc13x2_v1.am4fg),不过也是有源代码供参考的,就是 kernel/nortos/startup/startup_cc13x2_cc26x2_gcc.c 里面。

void __attribute__((naked)) resetISR(void)
{
    __asm__ __volatile__ (
        " movw r0, #:lower16:resetVectors\n"
        " movt r0, #:upper16:resetVectors\n"
        " ldr r0, [r0]\n"
        " mov sp, r0\n"
        " bl localProgramStart"
    );
}

很简单,设置堆栈指针后,直接转 localProgramStart() 函数执行。 后者在初始化 data, bss 之前,会调用两个函数:

    IntMasterDisable();
    /* Final trim of device */
    SetupTrimDevice();

  此处要补充一下,在编译后的代码中,实际上是调用 NOROM_CPUcpsid 和 NOROM_SetupTrimDevice 两函数,反汇编或者看ELF文件的符号表都能发现。函数名是怎么变的?原来是在一些 .h 文件里面,利用 #define 对名称进行了替换,结果就是同一套 C 程序可以编译出来不同版本的库,不同版本库里面的符号表(函数名)不同。如此做法可以防止库被混用,但对跟踪调试就造成一定的干扰了。

  接下来,在 SetupTrimDevice() 函数里面(文件在 source/ti/devices/cc13x2_cc26x2_v1/driverlib/setup.c),

    ThisLibraryIsFor_CC13x2_CC26x2_HwRev1x_HaltIfViolated();
    // Enable standby in flash bank
    HWREGBITW( FLASH_BASE + FLASH_O_CFG, FLASH_CFG_DIS_STANDBY_BITN ) = 0;

    // Select correct CACHE mode and set correct CACHE configuration
#if ( CCFG_BASE == CCFG_BASE_DEFAULT )
    SetupSetCacheModeAccordingToCcfgSetting();
#else
    NOROM_SetupSetCacheModeAccordingToCcfgSetting();
#endif

  我跟踪发现,SetupSetCacheModeAccordingToCcfgSetting() 是ROM中的代码。具体怎么实现?

  在被 setup.c 包含的 setup_rom.h 中,有如下宏定义:

//*****************************************************************************
//
// Support for DriverLib in ROM:
// Redirect to implementation in ROM when available.
//
//*****************************************************************************
#if !defined(DRIVERLIB_NOROM) && !defined(DOXYGEN)
    #include "../driverlib/rom.h"
...
    #ifdef ROM_SetupSetCacheModeAccordingToCcfgSetting
        #undef  SetupSetCacheModeAccordingToCcfgSetting
        #define SetupSetCacheModeAccordingToCcfgSetting ROM_SetupSetCacheModeAccordingToCcfgSetting
    #endif
...
#endif

  看出来是把函数名称替换成带 ROM_ 前缀的。然后找 rom.h 中的定义:

#define ROM_SetupSetCacheModeAccordingToCcfgSetting \
    ((void (*)(void)) \
    ROM_API_SETUP_ROM_TABLE[18])

  于是 SetupSetCacheModeAccordingToCcfgSetting() 成为了一个函数指针引用,入口地址在 ROM_API_SETUP_ROM_TABLE+18*4. 而根据

#define ROM_API_SETUP_ROM_TABLE  ((uint32_t*) (ROM_API_TABLE[28]))
#define ROM_API_TABLE           ((uint32_t *) 0x10000180)

  得知 API 的定位是先从 0x10000180 也就是 API 总表的地址索引第29项得到 SETUP API 表的地址,再查 SETUP API 表的第19项获得 SetupSetCacheModeAccordingToCcfgSetting 函数入口地址。

  在 GDB 里面验证一下:

(gdb) x /wx 0x10000180+28*4
0x100001f0:     0x100004bc
(gdb) x /wx 0x100004bc+18*4
0x10000504:     0x10004817

  即 SetupSetCacheModeAccordingToCcfgSetting 函数位于 ROM 地址 0x10004816 处,与 GDB 跟踪执行看到的地址一致。
  此外,在 setup_rom.c 里面实现了这个函数,不过编译时替换为带 NOROM_ 前缀的了,最终也没有被放到代码里面(不被引用,丢弃掉)。


此内容由EEWORLD论坛网友cruelfox原创,如需转载或用于商业用途需征得作者同意并注明出处

此帖出自RF/无线论坛

最新回复

感谢分享,每个步骤写的很详细   详情 回复 发表于 2019-7-7 22:22
点赞 关注(1)
 

回复
举报

1万

帖子

2853

TA的资源

管理员

沙发
 

感谢分享,每个步骤写的很详细

此帖出自RF/无线论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
个人签名玩板看这里:
https://bbs.eeworld.com.cn/elecplay.html
EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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