页次: 1
整理过的寄存器头文件tk499.h.zip
之前上边挖出来了SDRAM的初始化配置,理论上来讲可以按照比如2440这类的自己写下载算法和调试配置了,官方给的下载算法经常下载失败,估计是初始化文件有问题,有兴趣的老哥可以继续钻研下去
搞定,翻手册翻的眼睛快花了,感觉完全是在浪费时间
MM32具体对比型号是MM32F103,STM32是STM32F429,其中MM32F103有Rev N和Rev O两个版本,已经标注在表中
总结一下就是大部分外设理论上都可以直接copy MM32F103的库文件,TIM稍微改改就能用,I2C、BKP只需小改,RCC需要对照F429和手册改动,SPI需要对着手册改动,LCD/TK80应该是自己家的IP,这两个和I2S/QSPI还只能依靠官方库
另外附上MM32F103和TK499的手册,对比有惊喜
UM_TK499.pdf
UM_MM32F103xx_n_V1.69_SC.pdf
UM_MM32F103xx_o_V1.17_SC.pdf
附上对比的Excel
TK499寄存器对比.xlsx
那么就用MCO挖掘出真相吧。先不设置,直接将MCO开启,拿出我山上的Logic16
Logic16采样率100M,那这频率高过25M了,不会准确,不过就先暂且算50M左右。接着读出此时RCC->CFGR寄存器第22-20位是0b100,发现跟官方手册对上了,其中HSI内部高速时钟是48M
试了下将PLL频率设置到24M并且将MCO设置为PLLCLK/2,实际采集出来也是12M左右。OK,官方手册的寄存器应该没错,官方程序的PLL设置也没错。那么,对于APB的时钟设置该信哪一个呢?还是不知道。
然后,另一个问题来了,RCC_GetClocksFreq获得的ADC Clock是什么鬼。官方手册中的时钟树是这样的:
然后ADC章节也说ADC时钟是由RCC部分的寄存器设置:
但是,我**翻遍了官方手册的RCC寄存器也没发现ADC CLK相关设置。怎么办呢,去找F429爸爸的手册呗。F429的ADC CLK的分频是在ADC部分的寄存器里。回来翻TK499的官方手册ADC部分:
嗯,有问题找爸爸
接着来,默认工程设置初始化后调用RCC_GetClocksFreq函数发现APB1、APB2都跑在核心同频。
00> CPU Freq: 240 MHz
00> SYS Freq: 240 MHz
00> HCLK Freq: 240 MHz
00> PCLK1 Freq: 240 MHz
00> PCLK2 Freq: 240 MHz
00> ADC Freq: 120 MHz
STM32的经验告诉我这两个应该分别四分频和二分频才对,翻了下手册也一样提示有最高频率。
那就自己设置下呗,先按照STM32传统,调用库中的RCC_PCLK1Config四分频和RCC_PCLK2Config二分频,然后再打印下。
00> CPU Freq: 240 MHz
00> SYS Freq: 240 MHz
00> HCLK Freq: 240 MHz
00> PCLK1 Freq: 120 MHz
00> PCLK2 Freq: 120 MHz
00> ADC Freq: 60 MHz
这什么鬼,然后又试了几个分频参数,更离谱。感觉说不定是这俩函数错了,那就自己直接寄存器赋值吧。结果还不对。那怀疑点就落在RCC_GetClocksFreq函数了,点开一看
/* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*/
/* Get HCLK prescaler */
tmp = RCC->CFGR & CFGR_HPRE_Set_Mask;
tmp = tmp >> 4;
presc = APBAHBPrescTable[tmp];
/* HCLK clock frequency */
RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc;
/* Get PCLK1 prescaler */
tmp = RCC->CFGR & CFGR_PPRE1_Set_Mask;
tmp = tmp >> 8;
presc = APBAHBPrescTable[tmp];
/* PCLK1 clock frequency */
RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
/* Get PCLK2 prescaler */
tmp = RCC->CFGR & CFGR_PPRE2_Set_Mask;
tmp = tmp >> 11;
presc = APBAHBPrescTable[tmp];
/* PCLK2 clock frequency */
RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
/* Get ADCCLK prescaler */
tmp = RCC->CFGR & CFGR_ADCPRE_Set_Mask;
tmp = tmp >> 14;
presc = ADCPrescTable[tmp];
/* ADCCLK clock frequency */
RCC_Clocks->ADCCLK_Frequency = RCC_Clocks->PCLK2_Frequency / presc;
然后附上TK499,F429,F103分别的RCC->CFGR描述
名侦探时间到,两种假设:
1、TK499=F429=手册,毕竟TK499和F429怎么看怎么像,库直接copy103的;
2、TK499=F103=库,毕竟官方代码都用这么久了也没出事,肯定是手册有问题。
啧啧,味出来了,程序的第一行代码就得自己猜。
之前的折腾大概就这么多,接下来边填坑边写帖子了。
另外迫于Apple M1真香,现在工作环境都在向mac-arm64迁移。嵌入式这边Jlink以及配套的JFlash和Segger全家桶都有OSX版本,其中JFlash甚至已经有arm64版本了。arm gcc肯定是可以运行,pyocd和openocd也完全没问题,各种link基本都有驱动,开源软件跨平台是真的爽。STM32一套工具链CubeMX+Clion+openocd开发体验非常不错。
不过到TK499这就出问题了。之前有大佬已经写好了TK499的工程,编译完全正常,但下载调试有问题了。首先是TK499官方的USB拖拽下载,虽然烧录过程很快,但插入电脑到电脑弹出盘符估计能有1分多钟,在win10上和mac上都一样,这样效率极其低下。
在WIN10上官方提供了Keil环境下的下载算法FLM文件,可以用Jlink下载,实际体验还不错。FLM是标准的CMSIS下载算法格式,JFlash和pyocd都可以识别,wo也试着将算法添加到两个平台的JFlash和pyocd下,但是无论哪个平台哪个软件下载都会出问题。具体现象是写入完后TK499会自动跳到一级BL的USB下载状态,应该是没有检测到QSPI Flash中的固件头。而且由于跳转的是一级BL,所以可能QSPI Flash中的二级BL也被擦掉了。这种情况在Keil中如果选择全片擦除也会出现,选扇区擦除就可以避免。但是在Jflash和pyocd下即使选择扇区擦除也还是不行,并且根据下载时间判断应该也并没有全片擦除。
这个问题不知道有没有大佬能给点提示呢?
附上JFlash的XML代码
<Device>
<ChipInfo Vendor="HJR" Name="TKM32F499GT8" WorkRAMAddr="0x70020000" WorkRAMSize="0xF000" Core="JLINK_CORE_CORTEX_M4"/>
<!-- MCU does not have memory mapped flash area, instead a virtuell address is used. -->
<FlashBankInfo Name="External QSPI (via SPI)" BaseAddr="0x70020000" MaxSize="0x00200000" Loader="Devices/TKM32F499GT8.FLM" LoaderType="FLASH_ALGO_TYPE_CMSIS" />
</Device>
和pyocd的代码target_TKM32F499GT8.py.zip
接着跟踪ROM的汇编吧。接着SDRAM控制器初始化完成了就是冗长的内存拷贝,大概从ROM拷贝了8KB以上的数据到SDRAM首地址即0x70000000开始的空间,看来SDRAM初始的空间一级BL也使用了。这段拷贝追踪非常折磨人,到处跳转+循环,只能一次次在B/BX处设断点,然后不断F11。
拷贝完成了应该就进入C的世界了。接着就是向0x4002 3800开始的寄存器写数据,查看寄存器地址:
现在应该开始初始化RCC了。RCC的寄存器有详细列表,但是我实在懒得追了,也没啥必要。继续往下,初始化PA端口,应该是检查PA1和PA13以及初始化USB的端口。然后就实在懒得追了,能推断出之后大概就是判断QSPI Flash中的固件头和PA1 PA13状态并且跳转到对应启动方式。
一级Bootloader应该就是这些内容了。汇编我是真不太会,反汇编更是知识盲区,追这一大坨代码折腾了快4个小时,就这样吧……
复位后第一个跳转到0x1c0,开始分析
0x000001C0 F04F40E0 MOV r0,#0x70000000
0x000001C4 F04F4150 MOV r1,#0xD0000000
0x000001C8 6148 STR r0,[r1,#0x14]
将0x70000000写入0xD0000000+0x14,那么0xD0000000+0x14是什么寄存器呢
好家伙,还真是第一步上来就初始化SDRAM。接着是直到下一个BX的整段函数:
0x000001C0 F04F40E0 MOV r0,#0x70000000
0x000001C4 F04F4150 MOV r1,#0xD0000000
0x000001C8 6148 STR r0,[r1,#0x14]
0x000001CA F04F0000 MOV r0,#0x00
0x000001CE F04F4150 MOV r1,#0xD0000000
0x000001D2 F8C10084 STR r0,[r1,#0x84]
0x000001D6 F04F4050 MOV r0,#0xD0000000
0x000001DA 6800 LDR r0,[r0,#0x00]
0x000001DC F24501B0 MOVW r1,#0x50B0
0x000001E0 4388 BICS r0,r0,r1
0x000001E2 F04F4150 MOV r1,#0xD0000000
0x000001E6 6008 STR r0,[r1,#0x00]
0x000001E8 F04F4050 MOV r0,#0xD0000000
0x000001EC 6800 LDR r0,[r0,#0x00]
0x000001EE F6427148 MOVW r1,#0x2F48
0x000001F2 4308 ORRS r0,r0,r1
0x000001F4 F04F4150 MOV r1,#0xD0000000
0x000001F8 6008 STR r0,[r1,#0x00]
0x000001FA F04F4050 MOV r0,#0xD0000000
0x000001FE 6D40 LDR r0,[r0,#0x54]
0x00000200 F02000F7 BIC r0,r0,#0xF7
0x00000204 F04F4150 MOV r1,#0xD0000000
0x00000208 6548 STR r0,[r1,#0x54]
0x0000020A F04F4050 MOV r0,#0xD0000000
0x0000020E 6D40 LDR r0,[r0,#0x54]
0x00000210 F0400008 ORR r0,r0,#0x08
0x00000214 F04F4150 MOV r1,#0xD0000000
0x00000218 6548 STR r0,[r1,#0x54]
0x0000021A 2032 MOVS r0,#0x32
0x0000021C F04F4150 MOV r1,#0xD0000000
0x00000220 6108 STR r0,[r1,#0x10]
0x00000222 2032 MOVS r0,#0x32
0x00000224 F04F4150 MOV r1,#0xD0000000
0x00000228 F8C100AC STR r0,[r1,#0xAC]
0x0000022C F04F4050 MOV r0,#0xD0000000
0x00000230 68C0 LDR r0,[r0,#0x0C]
0x00000232 F42070E4 BIC r0,r0,#0x1C8
0x00000236 F04F4150 MOV r1,#0xD0000000
0x0000023A 60C8 STR r0,[r1,#0x0C]
0x0000023C F04F4050 MOV r0,#0xD0000000
0x00000240 68C0 LDR r0,[r0,#0x0C]
0x00000242 F0400081 ORR r0,r0,#0x81
0x00000246 F04F4150 MOV r1,#0xD0000000
0x0000024A 60C8 STR r0,[r1,#0x0C]
0x0000024C 4805 LDR r0,[pc,#20] ; @0x00000264
0x0000024E 4700 BX r0
翻译了下,大概是
向0xD0000000+0x14写入0x70000000
向0xD0000000+0x84写入0x00000000
读0xD0000000的值并与0x000050B0按位清零后写回
读0xD0000000的值并与0x00002F48取或后写回
读0xD0000000+0x54的值并与0x000000F7按位清零后写回
读0xD0000000+0x54的值并与0x00000008取或后写回
向0xD0000000+0x10写入0x00000032
向0xD0000000+0xAC写入0x00000032
读0xD0000000+0x0C的值并与0x000001C8按位清零后写回
读0xD0000000+0x0C的值并与0x00000081取或后写回
跳转
这时,观察0xD0000000开始的内存空间,直到用户程序开始运行,这段内存空间都不会再改动,那么所有代码中跟SDRAM控制器有关的应该就这一段了。
但是,但是,官方手册中并没有给SDRAM控制器的寄存器,并且这些寄存器跟F429的SDRAM控制器完全对不上,好了,卡死了。
挺好奇SDRAM的初始化是在哪一步进行的,但是SDRAM的初始化代码是在内置ROM中进行的,所以得去挖内置ROM。已知ROM的地址,直接JFlash伺候,从0x1FFF0000开始dump就好了。但是还不知道长度,多试了几次,程序还挺长,超过了64KB,直接dump了96KB,文件在此:tk499_rom.bin.zip。
有了bin,ida伺候,但是ida对ARM的分析是在不太行,核心寄存器的值基本出不来,直接反汇编看来不行。
这时突然想到Keil直接调试不就好了,复位,PC指向0x1c0,汇编也出来了。
接下来就是一步步F11了。
接着分析SDRAM开始的128KB干嘛了,在官方这个远程升级的帖子TKM32F499远程更新参考程序里,提到可以自己制作二级BL,并且给出了二级BL工程的内存设置:
ROM使用了0x70008000开始的60KB,而之前的32KB则作为RAM,所以SDRAM开始的128KB应该提供给二级BL使用了,实际进入主程序后这段空间也应该可以使用。
接着看了下工程初始化代码,在main最初的一个看名字是中断向量表重映射的函数吸引了我的注意,点进去:
void RemapVtorTable(void)
{
int i;
RCC->AHB1ENR |= 1<<13;//bkp clk,enable sram
//关ROM区中断
for(i = 0;i<90;i++)
{
NVIC_DisableIRQ((IRQn_Type)i);
}
SCB->VTOR = 0;
SCB->VTOR |= 0x1<<29;
for(i = 0;i < 512;i+=4)
*(u32*)(T_SRAM_BASE + i) = *(u32*)(T_SDRAM_BASE+i);
}
第一句注释,SRAM!接着就是正常的关中断,这时的中断应该还映射在ROM也就是0x0地址。然后将中断向量映射到0x20000000,对比F429的地址,这应该就是SRAM的地址了,随后拷贝循环中的T_SRAM_BASE也证实内部其实还留有SRAM并且地址从0x20000000开始。这个函数将SDRAM中程序头的2KB拷贝到SRAM,但是CM4中断向量表应该只有1KB,没太搞懂。这时已经挖出来内置SRAM地址,但是还不知道大小是多少。写个函数测了下,SRAM的尾地址应该是0x20004000,也就是16KB。激动,挖出来了宝贵的SRAM,排除1KB的中断向量,还有15KB可以用。
由于官方手册没有写出,担心是不是SRAM有硬件问题,写了个循环读写测试函数跑了几千轮,没出现错误,应该可以用。另外SRAM的频率与核心频率绑定,当核心跑在标称的240MHz时SRAM一切正常,但是稍微调高一点频率,SRAM的读写就开始出错,所以想使用SRAM就不能超频。同时官方代码将中断向量拷贝到SRAM里,意味着只要程序使用中断就不能超一点频率,只能在240MHz跑,这点需要注意,之前坑了我好久。
另外拿循环测了下内置SRAM的速度,-O3 + LTO尽量避免循环的损失,实际测试写入16KB用来120us,考虑到代码在SDRAM中的CPU取指损耗,内部SRAM的速度应该还是正常的。
接下来分析下内存映射,首先对比下TK499和F429的映射表:
可以看到TK499阉割掉了0x08000000开始的Flash,0x10000000开始的64KB CCMRAM,0x20000000开始的192K SRAM,而0x00000000地址由BOOT引脚决定后映射为0x1FFF0000开始的ROM。上电后PC指向0x0直接从ROM开始运行。TK499的映射表中没有发现一片SRAM令我挺好奇,难道bootloader上来就初始化SDRAM么。接着看了下工程的ROM和RAM分配:
ROM为0x70020000开始的2MB空间,RAM接着ROM,从0x70220000开始的8MB剩余空间。所以可以看出SDRAM的映射地址应该是从0x70000000开始,但是ROM为什么从0x20000的偏移开始,前面的128K不知道干什么了。
TK499相比F429,SIP了sdram,但也同时阉割掉了内置的Flash和SRAM,同时不支持从QSPI XIP启动,所以启动流程跟ARM9和CortexA系列比较相似。
首先TK499的Boot脚固定拉低,此时的启动方式对应STM32的内置Bootloader启动模式,即从内部固化的ROM中启动,随后初始化SDRAM,并将QSPI中的程序拷贝至SDRAM,然后跳转到SDRAM中执行。
官方推荐的下载方式是USB drag-and-drop,为此提供了一个二级bootloader。在复位时按住PA13,此时进入一级Bootloader即内置固化的BL,用来烧录二级BL至QSPI Flash。已经烧录二级BL后在复位时按住PA11将进入二级BL,此时就可以拖拽下载主程序。
根据官方放出的手册,TK499应该是STM32F429的Core,外挂了一块8M的32bit sdram,程序存在外置spi flash上,启动时拷贝到sdram执行。很好奇SDRAM执行代码的效率,就先移植了Coremark上去跑了下。ARMCC v6.14,开启FPU,-O3,LTO,一通操作,然后得到了如下跑分:
00>
00> CPU Freq: 240 MHz
00> SYS Freq: 240 MHz
00> HCLK Freq: 240 MHz
00> PCLK1 Freq: 240 MHz
00> PCLK2 Freq: 240 MHz
00> ADC Freq: 120 MHz
00> Start.
00> 2K performance run parameters for coremark.
00> CoreMark Size : 666
00> Total ticks : 21042
00> Total time (secs): 21
00> Iterations/Sec : 142
00> Iterations : 3000
00> Compiler version : GCCClang 11.0.0
00> Compiler flags : -o3
00> Memory location : STACK
00> seedcrc : 0xE9F5
00> [0]crclist : 0xE714
00> [0]crcmatrix : 0x1FD7
00> [0]crcstate : 0x8E3A
00> [0]crcfinal : 0xCC42
00> Correct operation validated. See README.md for run and reporting rules.
00> CoreMark 1.0 : 142 / GCCClang 11.0.0 -o3
嗯,240MHz的M4F跑出了F103的水平,Coremark/MHz分数还不如AVR。
超频,更改优化,在ARMCC v6.14,开启FPU, 312MHz,-Oz下获得了最高分
00>
00> CPU Freq: 312 MHz
00> SYS Freq: 312 MHz
00> HCLK Freq: 312 MHz
00> PCLK1 Freq: 312 MHz
00> PCLK2 Freq: 312 MHz
00> ADC Freq: 156 MHz
00> Start.
00> 2K performance run parameters for coremark.
00> CoreMark Size : 666
00> Total ticks : 11987
00> Total time (secs): 11
00> Iterations/Sec : 272
00> Iterations : 3000
00> Compiler version : GCCClang 11.0.0
00> Compiler flags : -Oz
00> Memory location : STACK
00> seedcrc : 0xE9F5
00> [0]crclist : 0xE714
00> [0]crcmatrix : 0x1FD7
00> [0]crcstate : 0x8E3A
00> [0]crcfinal : 0xCC42
00> Correct operation validated. See README.md for run and reporting rules.
00> CoreMark 1.0 : 272 / GCCClang 11.0.0 -Oz
最高分下Coremark/MHz也没超过1,还不如M0。
作为对比,1原版F429跑在Flash里配合art加速能拿到3以上的Coremark/MHz,没有art加速的F303能拿到2.5左右的分数,同样运行在SDRAM的F1C100S就算arm9内核也能到2以上。没有Cache的情况下在SDRAM中运行性能损失是真的大,-Oz比-O3/LTO的性能能高出一倍说明SDRAM带宽的瓶颈很明显,在平时使用中如果接RGB屏的话,带宽还会被占用一大截,性能下降还会更明显。另外提供个之前测过的数据,NXP KV58,240MHz的CortexM7,Flash频率只有20-25MHz,开启Cache的情况下能拿到5 Coremark/MHz,关闭Cache分数暴跌到1.5。
同时测了下TK499的功耗,默认GPIO工程,移植Coremark,没有开启其他外设,240MHz空载大概115ma,运行Coremark时125ma;超频到312MHz空载128ma,满载145ma。运行时芯片手摸上去温热,估计30几度左右。
根据功耗来看制程大概还是STM32F4的90nm,比不上现在有些上到55nm/40nm的新一批国产MCU。
经常买Tiky家的屏,所以TKM32F499这块MCU刚出来的时候就开始关注了。最近开挖新坑,需要找一个1MB以上的内存+8080并口的MCU,H750吧内置SRAM不够QSPI又不能写映射所以挂PSRAM不方便,ESP32吧可以I2S模拟8080但是IO口不够用,GD新出的E50x系列可以QSPI写映射挂PSRAM但是只有144脚才引出QSPI,格力那个EAI80看着不错但是买不到,找来找去还是回到TK499,sip的8M SDRAM配合20多点价格还是很诱人的。
Tiky家自己的核心板IO引出不太理想,所以买了裸片自己重新画了一个核心板。TK499的IO布局很不错,同一复用功能的基本连续,我布核心板的时候很方便的就把RGB/8080/Touchpad连到了同一侧,另一侧是剩下的PA、PC和ADC,SD卡和QSPI FLASH线序也很整齐。另外为了以后方便接屏,直接在核心板上加了个通用RGB40Pin接口。手头只有0805的元器件,所以各种阻容占了很大的面积,快过年了怕快递停运,急急忙忙画完就发出去了,布线也没太讲究。
需要注意的是TK499的封装是0.4pitch的LQFP128,体积跟0.5pitch的LQFP100一样大,芯片底部其实有个热焊盘,但官方封装没给,实际不连接也不影响,这片子也不用太考虑散热问题。另外应该是内置Bootloader也使用外部晶振,所以必须使用外部晶振且频率必须为12M,实测不接晶振的话Bootloader无法运行,SWD可以探测到芯片但连接失败。
手头没洗板水,两面都是元器件又没法上加热台,实在有点丑……
另外强烈推荐kicad这个HTML交互式BOM,焊接时不要太方便。名字是InteractiveHtmlBom,GitHub直接搜就有。
附上PCB工程文件,画的实在太赶不怎么讲究,原理图画的到处都是……
tkm32f499_core.zip
基础元件属于同一级别。看店家的拆解图:
- 加速计是飞思卡尔的MMA8451,3轴14bit;
- 地磁罗盘是霍尼韦尔的HMC5883L,3轴12bit;
- 还有一片QFN-20的丝印看不清。
- 板载STM32F205,在原始数据的基础上做了姿态融合的处理,用的什么算法不得而知,但肯定受限于cortex-m3的算力,要是F4系列可能更好。(搜索关键字,AHRS,mahony,卡尔曼滤波等)。用模块的好处是,可以避免自己去研究算法,传感器矫正、甚至温度补偿这些很容易影响最终测量性能的坑。
当然,坏处就是不灵活,功耗、体积、算法优化等没法自己调整。
120MHz的M3做100HZ的EKF应该够了
QFN20的芯片应该是陀螺仪,其实应该是两边3引脚,两边5引脚的QFN16,我猜是ST的LIS3DH或者类似型号
原始数据肯定比不上现在新的MEMS芯片,但是这种模块应该是针对于芯片特性做了相关处理,也应该进行过校准,最终输出数据应该比9250这种DMP库直出好些
飞思卡尔小白有问题:
1. KSDK 是不是飞思卡尔官方SDK? 在哪里下载?
2. 用32.768k的目的是什么?为了休眠的时候RTC还能跑?
3. 如何超频?非常感谢这个矩阵键盘资料, 晚上我试一试.
1.对的,而且目前NXP家的LPC和RT官方SDK也叫KSDK了,在https://mcuxpresso.nxp.com可以下载,需要NXP官网账号,注册一个就是了。网站服务器在日本,所以晚上高峰期访问比较慢。
2.说的是外置的32.768还是内置的32.768?外置的估计就是为了RTC走的更稳,用内置的32.768是因为内置锁频环只能由内置32.768输入
3.超频我是直接更改的MCG寄存器,官方库配置时钟我只搞明白了PLL的配置方法,FLL的还没搞明白
以下是目前的时钟配置
/*******************************************************************************
* Variables for BOARD_BootClockRUN configuration
******************************************************************************/
const mcg_config_t mcgConfig_BOARD_BootClockRUN =
{
.mcgMode = kMCG_ModeFEI, /* FEI - FLL Engaged Internal */
.irclkEnableMode = kMCG_IrclkEnable, /* MCGIRCLK enabled, MCGIRCLK disabled in STOP mode */
.ircs = kMCG_IrcSlow, /* Slow internal reference clock selected */
.fcrdiv = 0x0U, /* Fast IRC divider: divided by 1 */
.frdiv = 0x0U, /* FLL reference clock divider: divided by 32 */
.drs = kMCG_DrsMid, /* Mid frequency range */
.dmx32 = kMCG_Dmx32Fine, /* DCO is fine-tuned for maximum frequency with 32.768 kHz reference */
.oscsel = kMCG_OscselOsc, /* Selects System Oscillator (OSCCLK) */
.pll0Config =
{
.enableMode = MCG_PLL_DISABLE, /* MCGPLLCLK disabled */
.prdiv = 0x3U, /* PLL Reference divider: divided by 4 */
.vdiv = 0x0U, /* VCO divider: multiplied by 24 */
},
};
const sim_clock_config_t simConfig_BOARD_BootClockRUN =
{
.pllFllSel = SIM_PLLFLLSEL_MCGPLLCLK_CLK, /* PLLFLL select: MCGPLLCLK clock */
.er32kSrc = SIM_OSC32KSEL_RTC32KCLK_CLK, /* OSC32KSEL select: RTC32KCLK clock (32.768kHz) */
.clkdiv1 = 0x01030000U, /* SIM_CLKDIV1 - OUTDIV1: /1, OUTDIV2: /1, OUTDIV4: /2 */
};
const osc_config_t oscConfig_BOARD_BootClockRUN =
{
.freq = 0U, /* Oscillator frequency: 0Hz */
.capLoad = (OSC_CAP0P), /* Oscillator capacity load: 0pF */
.workMode = kOSC_ModeOscLowPower, /* Oscillator low power */
.oscerConfig =
{
.enableMode = kOSC_ErClkEnable, /* Enable external reference clock, disable external reference clock in STOP mode */
}
};
/*******************************************************************************
* Code for BOARD_BootClockRUN configuration
******************************************************************************/
void BOARD_BootClockRUN(void)
{
/* Set the system clock dividers in SIM to safe value. */
CLOCK_SetSimSafeDivs();
/* Set MCG to FEI mode. */
#if FSL_CLOCK_DRIVER_VERSION >= MAKE_VERSION(2, 2, 0)
CLOCK_BootToFeiMode(mcgConfig_BOARD_BootClockRUN.dmx32,
mcgConfig_BOARD_BootClockRUN.drs,
CLOCK_CONFIG_FllStableDelay);
#else
CLOCK_BootToFeiMode(mcgConfig_BOARD_BootClockRUN.drs,
CLOCK_CONFIG_FllStableDelay);
#endif
MCG->C4 |= (MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS(0x03));
/* Configure the Internal Reference clock (MCGIRCLK). */
CLOCK_SetInternalRefClkConfig(mcgConfig_BOARD_BootClockRUN.irclkEnableMode,
mcgConfig_BOARD_BootClockRUN.ircs,
mcgConfig_BOARD_BootClockRUN.fcrdiv);
/* Set the clock configuration in SIM module. */
CLOCK_SetSimConfig(&simConfig_BOARD_BootClockRUN);
/* Set SystemCoreClock variable. */
SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK;
}
晕哥不来品尝下屎一样的NXP原厂固件库KSDK么,乐趣多多
SDK档案:https://pan.baidu.com/s/1yowvUOAFn5ma23VWznpOMw 密码:wkku,包含全部工具链和全部中间层组件
API手册地址:http://mcuxpresso.nxp.com/api_doc/dev/463/
另外晕哥对裸机下启动AP6210有什么对策么?我看Linux的驱动貌似初始化得先下载固件进去?
顺便简单介绍下NXP SDK档案的文件结构
目录下
device文件夹是原厂固件库
CMSIS文件夹是CMSIS层
middleware是中间层
rtos是freertos的BSP
boards文件夹是原厂开发板的例程,写KSDK基本靠它,API手册和RM写的都是一团糟,注意此文件夹下不是完整工程,没有将上述4个文件夹中在此工程所需的文件复制进来,如需获取完整的工程需要利用NXP的MCUXpresso Config Tools进行生成
MCUXpresso Config Tools类似于ST的STM32Cube MX,可以根据SDK生成工程,分配引脚,编辑时钟树
页次: 1