Go 语言在极小硬件上的运用(二)
文章插图
我将展示一个简单的示例 , 来说明如何定义和使用接口 , 以及如何利用无处不在的 io.Writer 接口 。
? 来源:linux.cn ? 作者:Micha? Derkacz ? 译者:XianLei Gao ?
(本文字数:21486 , 阅读时长大约:24 分钟)
在本文的 第一部分 的结尾 , 我承诺要写关于接口的内容 。 我不想在这里写有关接口或完整或简短的讲义 。 相反 , 我将展示一个简单的示例 , 来说明如何定义和使用接口 , 以及如何利用无处不在的 io.Writer 接口 。 还有一些关于 反射(reflection)和 半主机(semihosting)的内容 。
文章插图
]
stm32F030F4P6
接口是 Go 语言的重要组成部分 。 如果你想了解更多有关它们的信息 , 我建议你阅读《 高效的 Go 编程 》 和 Russ Cox 的文章。
并发 Blinky – 回顾当你阅读前面示例的代码时 , 你可能会注意到一中打开或关闭 led 的反直觉方式 。Set 方法用于关闭 LED , Clear 方法用于打开 LED 。 这是由于在 漏极开路配置(open-drain configuration) 下驱动了 LED 。 我们可以做些什么来减少代码的混乱?让我们用 On 和 Off 方法来定义 LED 类型:
type LED struct {pin gpio.Pin}func (led LED) On() {led.pin.Clear()}func (led LED) Off() {led.pin.Set()}
现在我们可以简单地调用 led.On() 和 led.Off() , 这不会再引起任何疑惑了 。
在前面的所有示例中 , 我都尝试使用相同的 漏极开路配置(open-drain configuration)来避免代码复杂化 。 但是在最后一个示例中 , 对于我来说 , 将第三个 LED 连接到 GND 和 PA3 引脚之间并将 PA3 配置为 推挽模式(push-pull mode)会更容易 。 下一个示例将使用以此方式连接的 LED 。
但是我们的新 LED 类型不支持推挽配置 , 实际上 , 我们应该将其称为 OpenDrainLED , 并定义另一个类型 PushPullLED:
type PushPullLED struct {pin gpio.Pin}func (led PushPullLED) On() {led.pin.Set()}func (led PushPullLED) Off() {led.pin.Clear()}
请注意 , 这两种类型都具有相同的方法 , 它们的工作方式也相同 。 如果在 LED 上运行的代码可以同时使用这两种类型 , 而不必注意当前使用的是哪种类型 , 那就太好了 。接口类型可以提供帮助:
package mainimport ("delay""stm32/hal/gpio""stm32/hal/system""stm32/hal/system/timer/systick")type LED interface {On()Off()}type PushPullLED struct{ pin gpio.Pin }func (led PushPullLED) On(){led.pin.Set()}func (led PushPullLED) Off() {led.pin.Clear()}func MakePushPullLED(pin gpio.Pin) PushPullLED {pin.Setup( --tt-darkmode-color: #42962A;">可赋值性(assignability)在编译时检查 。 赋值后 , led1 变量包含一个 OpenDrainLED{gpio.A.Pin(4)} , 以及一个指向 OpenDrainLED 类型的方法集的指针 。led1.On() 调用大致对应于以下 C 代码:
led1.methods->On(led1.value)
如你所见 , 如果仅考虑函数调用的开销 , 这是相当廉价的抽象 。
但是 , 对接口的任何赋值都会导致包含有关已赋值类型的大量信息 。 对于由许多其他类型组成的复杂类型 , 可能会有很多信息:
$ egc$ arm-none-eabi-size cortexm0.elftextdatabssdechex filename10356196212107642a0c cortexm0.elf
如果我们不使用 反射, 可以通过避免包含类型和结构字段的名称来节省一些字节:
$ egc -nf -nt$ arm-none-eabi-size cortexm0.elftextdatabssdechex filename103121962121072029e0 cortexm0.elf
生成的二进制文件仍然包含一些有关类型的必要信息和关于所有导出方法(带有名称)的完整信息 。 在运行时 , 主要是当你将存储在接口变量中的一个值赋值给任何其他变量时 , 需要此信息来检查可赋值性 。
我们还可以通过重新编译所导入的包来删除它们的类型和字段名称:
$ cd $HOME/emgo$ ./clean.sh$ cd $HOME/firstemgo$ egc -nf -nt$ arm-none-eabi-size cortexm0.elftextdatabssdechex filename102721962121068029b8 cortexm0.elf
让我们加载这个程序 , 看看它是否按预期工作 。 这一次我们将使用 st-flash 命令:
$ arm-none-eabi-objcopy -O binary cortexm0.elf cortexm0.bin$ st-flash write cortexm0.bin 0x8000000st-flash 1.4.0-33-gd76e3c72018-04-10T22:04:34 INFO usb.c: -- exit_dfu_mode2018-04-10T22:04:34 INFO common.c: Loading device parameters....2018-04-10T22:04:34 INFO common.c: Device connected is: F0 small device, id 0x100064442018-04-10T22:04:34 INFO common.c: SRAM size: 0x1000 bytes (4 KiB), Flash: 0x4000 bytes (16 KiB) in pages of 1024 bytes2018-04-10T22:04:34 INFO common.c: Attempting to write 10468 (0x28e4) bytes to stm32 address: 134217728 (0x8000000)Flash page at addr: 0x08002800 erased2018-04-10T22:04:34 INFO common.c: Finished erasing 11 pages of 1024 (0x400) bytes2018-04-10T22:04:34 INFO common.c: Starting Flash write for VL/F0/F3/F1_XL core id2018-04-10T22:04:34 INFO flash_loader.c: Successfully loaded flash loader in sram 11/11 pages written2018-04-10T22:04:35 INFO common.c: Starting verification of write complete2018-04-10T22:04:35 INFO common.c: Flash written and verified! jolly good!
- 麒麟|荣耀新款,麒麟810+4800万超清像素,你还在犹豫什么呢?
- 智能手机市场|华为再拿第一!27%的份额领跑全行业,苹果8%排在第四名!
- 行业|现在行业内客服托管费用是怎么算的
- 零部件|马瑞利发力电动产品,全球第七大零部件供应商在转型
- 通气会|12月4~6日,2020中国信息通信大会将在成都举行
- 俄罗斯手机市场|被三星、小米击败,华为手机在俄罗斯排名跌至第三!
- 体验|闭上眼睛点外卖是什么感觉?时隔一年再次体验,进步令人欣慰
- 当初|这是我的第一部华为手机,当初花6799元买的,现在“一文不值”?
- 出海|出海日报丨短视频生产服务商小影科技完成近4亿元 C 轮融资;华为成为俄罗斯在线出售智能手机的第一品牌
- 看过明年的iPhone之后,现在下手的都哭了