灯厂们背后的MCU,看LPC如何花式点灯(之三)

EZH介绍完了之后,咱们介绍如何使用LPC55S69片上双核机制实现驱动WS2812灯带。

可能有大神说了,你完全可以用GPIO模拟WS2812的时序啊,何必用SPI和EZH来做。真么说对的,攻城狮认为这么写一篇单独的GPIO模拟WS2812的时序 不太划算太水了, 所以结合双核的应用来这么一篇。一来介绍了GPIO模拟WS2812,二来双核的工程建立和应用也介绍了,内容比较丰富些。

双核工程创建

LPC55S69的双核工程可以很方便的用MCUXpresso Config Tool工具创建。


利用MCUXpresso Config Tool 和SDK的实例模板 创建一个双核工程

新创建的工程,由于软件小bug,incbin.s并没有加入core0主核的工程,incbin.s 是一段汇编,用于把core1 固件的bin文件链接到core0的image中。
注意,Core1的固件是存储在Flash中的,上电的时候,由主核Core0搬运到RAM中,再通知Core1运行。

加入incbin.s

如何把core1的image 编译进 core0的image中

首先还是分散加载文件,在生成好的工程中,core0的分散加载文件已经给core1的image默认分配了一个空间,这个空间段的名字是m0code,地址从0x00072000,大小是0x00026000,用户可以根据自己的实际需求修改这个起始地址和重新分配空间的大小。


core0关于core1 固件安排的地址空间

前文我们提别提到了incbin.s,顾名思义incbin是insert binary的缩写,这个汇编文件,会帮我们把core1工程产生的binary文件core1_image.bin在在core0编译的过程中放到core1在分散加载文件中定义的空间段。


incbin.s如何插入core1的image固件

当然这么设置完,还不够。最后关于双核的设置还有一点,要在KEIL的工程配置选型卡里,选择“Asm”配置include的路径,将core1的image路径设置进来。


Asm include路径配置

Core1 用来做GPIO的控制驱动WS2812

由于Core1的代码比较直观且简单,我们就不用流程图来解释了。大概讲下Core1作为小核使用的过程。
第一步,调用MCMGR_Init()这个API,来初始化SDK提供的双核机制比如通用事件这类功能。
第二步,获取Core0启动Core1时传来的参数,这个代码里,Core0传递给Core1的是WS2812TxBuf,这个Buffer里包含的LED数据数组的长度和各个LED显示的RGB数据内容。
第三步,拉低WS2812 Data的IO口,延时大于50uS以上
第四步,按照每个WS2812TxBuf里实际RGB数据按照bit,翻转GPIO发出0/1 信号
第五步,发送完成后,调用MCMGR_TriggerEvent() API触发Core0的中断,通知主核Core1完成了WS2812数据的发送。
最后,调用MCMGR_StopCore() 把自己这个core1关闭掉。
注意,代码delay的配置是以96MHz主频来定的,如果改变的MCU的主频,这个值需要修改。


Core1代码

Core0 用来做数据整理并且通知Core1发送

这样做的好处是解放了Core0的资源,不会被各种delay函数浪费了资源。
Core0调用Core1的资源前,要先初始化SDK的双核管理机制
MCMGR_Init()
然后将Core1的Image从Flash 复制到其本身定义的RAM区域。
如果需要Core1在完成时触发中断通知,则用MCMGR_RegisterEvent()注册一个回调函数,在Core1中断发出的时候在Core0的中断处理函数中调用这个回调函数


core0初始化core1的代码

Core0启动Core1发送数据的方式比较简单,在整理好数据后,直接调用MCMGR_StartCore() API 即可。这里我们希望Core1和Core0之间是异步执行的,所以在第四个形参里使用的是异步模式。

Core0启动Core1

实际的点灯代码

实际的点灯代码的API,我这边将SPI,EZH,双核,SCT都是统一的,main函数里边的内容一样,参考EZH那篇(之二)末尾介绍的API即可。

你可能感兴趣的:(灯厂们背后的MCU,看LPC如何花式点灯(之三))