当前位置: 首页 > 科技观察

Go语言在极小硬件上的使用(一)

时间:2023-03-16 01:03:12 科技观察

Go语言,多低的配置能跑起来发挥作用?我最近购买了一块特别便宜的开发板:STM32F030F4P6。我买它是出于三个原因。首先,我(作为一个程序员)从来没有接触过STM320系列的开发板。其次,STM32F10x系列的使用也有点少。STM320系列MCU价格便宜,外设更新,系列改进,bug修复更好。最后,为了这篇文章,我选择了系列中配置最低的板子,整个事情变得有趣起来。STM32F030F4P6的硬件部分很牛逼:CPU:CortexM048MHz(最低配置,只有12000个逻辑门)RAM:4KB,Flash:16KB,ADC,SPI,I2C,USART和几个上面的定时器在TSSOP20封装。如您所见,这是一个微型32位系统。软件部分如果你想知道如何在这个开发板上使用Go编程,你需要反复阅读硬件规格手册。您必须面对一个事实,即Go编译器不太可能支持Cortex-M0。而且,这只是第一个要解决的问题。我将使用Emgo,但别担心,稍后您会看到它如何使Go在如此小的系统上尽可能有用。在我拿到这个开发板之前,stm32/hal系列下的F0单片机是不支持的。简单查阅参考手册后,我发现STM32F0系列是STM32F3的精简版,这使得在新端口上的开发更容易一些。如果你想按照本文的步骤,你需要安装emgocd$HOMEgitclonehttps://github.com/ziutek/emgo/cdemgo/egcgoinstall然后设置环境变量exportEGCC=path_to_arm_gcc#eg./usr/local/arm/bin/arm-none-eabi-gccexportEGLD=path_to_arm_linker#例如。/usr/local/arm/bin/arm-none-eabi-ldexportEGAR=path_to_arm_archiver#例如。/usr/local/arm/bin/arm-none-eabi-arexportEGROOT=$HOME/emgo/egrootexportEGPATH=$HOME/emgo/egpathexportEGARCH=cortexm0exportEGOS=noosexportEGTARGET=f030x6更详细的说明可以在Emgo上找到官方网站。确保egc在你的PATH上。您可以使用gobuild而不是goinstall并将egc复制到您的$HOME/bin或/usr/local/bin。现在,为您的第一个Emgo程序创建一个新文件夹,并复制示例链接描述文件:mkdir$HOME/firstemgocd$HOME/firstemgocp$EGPATH/src/stm32/examples/f030-demo-board/blinky/script.ld。基本程序在main.go文件中创建一个基本程序:packagemainfuncmain(){}文件编译没有任何问题:$egc$arm-none-eabi-sizecortexm0.elftextdatabssdechexfilename745217210477281e30cortexm0.elf第一次编译可能需要一段时间。编译后的二进制文件占用7624字节的Flash空间(文本+数据)。对于一个什么都不做的程序来说,它占用的空间很大。还剩下8760个字节,可以用来做一些有用的事情。试试传统的“你好,世界!”program:packagemainimport"fmt"funcmain(){fmt.Println("Hello,World!")}不幸的是,这次的结果有点糟糕:$egc/usr/local/arm/bin/arm-none-eabi-ld:/home/michal/P/go/src/github.com/ziutek/emgo/egpath/src/stm32/examples/f030-demo-board/blog/cortexm0.elf部分“.text”不会适合区域“Flash”/usr/local/arm/bin/arm-none-eabi-ld:区域“Flash”溢出10880字节退出状态1“Hello,World!”需要STM32F030x6计算机上至少32KB的闪存空间。fmt包强制包含整个strconv和reflect包。这三个包,即使在精简版的Emgo中,也会占用大量空间。我们不能再使用这个例子了。有许多应用程序不需要漂亮的文本输出。通常,一个或多个LED或七段显示器就足够了。但是,在第二部分中,我将尝试使用strconv包在UART上格式化和显示一些数字和文本。闪烁我们的电路板有一个LED连接到PA4引脚和VCC。这次我们的代码稍微长一点:.SetupPLL(8,1,48/8)systick.Setup(2e6)gpio.A.EnableClock(false)led=gpio.A.Pin(4)cfg:=&gpio.Config{Mode:gpio.Out,Driver:gpio.OpenDrain}led.Setup(cfg)}funcmain(){for{led.Clear()delay.Millisec(100)led.Set()delay.Millisec(900)}}按照惯例,init函数用于初始化和配置外围设备。system.SetupPLL(8,1,48/8)用于配置RCC使用外部8MHz振荡器PLL作为系统时钟源。PLL分频设置为1,倍频设置为48/8=6,所以系统时钟频率为48MHz。systick.Setup(2e6)每2e6纳秒(每秒500次)运行一次Cortex-MSYSTICK时钟作为系统时钟。gpio.A.EnableClock(false)启用GPIOA端口的时钟。False表示该时钟在低功耗模式下被禁用,但这在STM32F0系列中未实现。led.Setup(cfg)设置PA4引脚为开漏输出。led.Clear()将PA4引脚设置为低电平,在漏极开路设置中打开LED。led.Set()设置PA4为高电平,关闭LED。编译这段代码:$egc$arm-none-eabi-sizecortexm0.elftextdatabssdechexfilename9772172168101122780cortexm0.elf可以看到,blink程序占用了2320字节,比最基本的多了程序占用空间大。剩余6440字节。检查代码是否有效:$openocd-d0-finterface/stlink.cfg-ftarget/stm32f0x.cfg-c'init;程序cortexm0.elf;重置运行;exit'OpenOn-ChipDebugger0.10.0+dev-00319-g8f1f912a(2018-03-07-19:20)在GNUGPLv2下获得许可对于错误报告,请阅读http://openocd.org/doc/doxygen/bugs。htmldebug_level:0adapterspeed:1000kHzadapter_nsrst_delay:100noneseparateadapterspeed:950kHztargethaltedduetodebug-request,currentmode:ThreadxPSR:0xc1000000pc:0x0800119cmsp:0x20000da0adapterspeed:4000kHztargethaltedduetoerase**由于擦除启用目标编程停止断点,当前模式:ThreadxPSR:0x61000000pc:0x2000003amsp:0x20000da0wrote10240bytesfromfilecortexm0.elfin0.817425s(12.234KiB/s)**ProgrammingFinished**adapterspeed:950kHzInthisarticle,thisismyfirst时间,将短视频转换为动画PNG。我印象深刻,再见YouTube。抱歉,IE用户,请参阅apngasm了解更多信息。我应该学习HTML5,但现在APNG是我最喜欢的循环播放方法短视频。STM32F030F4P6更多Go编程如果你不是Go程序员,但听说过一些Go语言的东西,你可能会说:“Go语法不错,但是和C相比,没有明显的提升。我看看频道和Go语言的协程!”接下来我会一一展示:{system.SetupPLL(8,1,48/8)systick.Setup(2e6)gpio.A.EnableClock(false)led1=gpio.A.Pin(4)led2=gpio.A.Pin(5)cfg:=&gpio.Config{Mode:gpio.Out,Driver:gpio.OpenDrain}led1.Setup(cfg)led2.Setup(cfg)}funcblinky(ledgpio.Pin,periodint){for{led.Clear()延迟。Millisec(100)led.Set()delay.Millisec(period-100)}}funcmain(){goblinky(led1,500)blinky(led2,1000)}代码更改很小:添加了第二个LED,上一个示例中的main函数已重命名为blinky并且需要两个参数。main在新协程中先调用blinky,所以两个LED灯并联使用。值得一提的是,gpio.Pin可以同时访问同一个GPIO端口的不同引脚。Emgo有很多不足之处。其中之一就是需要提前指定goroutines(任务)的最大执行次数。是时候修改script.ld:ISRStack=1024;MainStack=1024;TaskStack=1024;MaxTasks=2;INCLUDEstm32/f030x4INCLUDEstm32/loadflashINCLUDEnoos-cortexm栈的大小需要猜,不用管然而。$egc$arm-none-eabi-sizecortexm0.elftextdatabssdechexfilename1002017217210364287ccortexm0.elf另一个LED和协程共占用248字节的Flash空间。STM32F030F4P6ChannelsChannels是Go语言中协程之间推荐的通信方式。Emgo甚至允许通过中断处理使用缓冲通道。下一个示例演示了这种情况。packagemainimport("delay""rtos""stm32/hal/gpio""stm32/hal/irq""stm32/hal/system""stm32/hal/system/timer/systick""stm32/hal/tim")var(leds[3]gpio.Pintimer*tim.Periphch=make(chanint,1))funcinit(){system.SetupPLL(8,1,48/8)systick.Setup(2e6)gpio.A.EnableClock(false)leds[0]=gpio.A.Pin(4)leds[1]=gpio.A.Pin(5)leds[2]=gpio.A.Pin(9)cfg:=&gpio.Config{模式:gpio.Out,驱动程序:gpio.OpenDrain}for_,led:=rangeleds{led.Set()led.Setup(cfg)}timer=tim.TIM3pclk:=timer.Bus().Clock()ifpclk