当前位置: 首页 > news >正文

d你好Arduino

原文
ldc支持gdc风格汇编
avrd
d的avr

两个选项可链接ldc发出的编译目标文件:用avr-gcc的链接器,或用llvm的内部链接器.-gcc=avr-gcc参数告诉在哪查找avr-gcc工具,或可用使用llvm的内置链接器的--link-internally.两者都会起作用.
使用-gcc相关的好处是可arduino studio,因为它有objcopy,avrdude等程序及其他有用的东西.让它正常工作,并更好地集成与其他库和工具等一起使用,如gcc提供的C运行时.

$ PATH=/opt/arduino/arduino-1.8.10/hardware/tools/avr/bin:$PATH ldc2 -betterC -Oz -mtriple=avr -mcpu=atmega328p -gcc=avr-gcc delay.d
$ file delay
delay: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, with debug_info, not stripped
$ ls -l delay
-rwxr-xr-x 1 me users 2440 Sep 18 08:28 delay

使用PATH中的arduino工具,-gcc=avr-gcc参数就可工作.
使用--link-internally,你不需要这些,但是:

$ ldc2 -betterC -Oz -mtriple=avr -mcpu=atmega328p --link-internally delay.d
lld: warning: cannot find entry symbol _start; defaulting to 0x110B4
$ file delay
delay: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, not stripped
$ ls -l delay
-rwxr-xr-x 1 me users 708 Sep 18 08:31 delay

注意它链接了,但它给出了关于丢失_start的警告.还要注意不同的文件大小.这是因为gcc提供的C运行时,提供了调用你的extern(C)main来执行一些基本设置开始符号.没有它,你需要自己做更多的事情.我敢肯定,你也可在链接命令中列举lib/object文件来让ldc链接,但是使用-avr-gcc,可正常工作,因为它已知道在哪可找到所有这些东西.

avr链接,有点过时.
可用标准的ldc2安装,只需从ldc网站获取二进制.你不必自己编译它;正常下载中,avr支持已有一段时间了.
得到ldc后,先安装arduino工具.我直接安装ArduinoStudio.我把文件放在/opt/arduino/arduino-1.8.10/中.你可能要调整该路径.在那里,你会看到arduino命令,硬件目录等.

me@arsd:/opt/arduino/arduino-1.8.10$ ls
arduino          arduino-linux-setup.sh  hardware    java  libraries  revisions.txt  tools-builder
arduino-builder  examples                install.sh  lib   reference  tools          uninstall.sh

写个测试:

import ldc.llvmasm;

// delay_basic.h中的移植
void _delay_loop_1(ubyte __count) {
//该模板参数是必需的,以避免
//`!Call.getType()->isVoidTy()&&"Badinlineasm!"'`断定失败.
        __asm!ubyte (
                "1: dec $0\n\tbrne 1b",
                "=r,0", (__count)
        );
}
void _delay_loop_2(ushort __count) {
        __asm!ushort (`
    1: sbiw $0,1
    brne 1b
    `,
    `=w,0`,
    __count);
}

// arduino 中 delay.h 的端口
enum F_CPU = 1000000UL;

 // 这是`_delay_ms`,但我做错了,把`double`改成`int`,我还是不喜欢
void _delay(int __ms) {
    ushort __ticks;
    ulong __tmp = (F_CPU * __ms) / 4000;
    if(__tmp < 1)
        __ticks = 1;
    else if(__tmp > 65535) {
        __ticks = cast(ushort) (__ms * 10.0);
        while(__ticks) {
            _delay_loop_2(cast(ushort) (((F_CPU) / 4e3) / 10));
            __ticks--;
        }
        return;
    } else
        __ticks = cast(ushort) __tmp;
    _delay_loop_2(__ticks);
}


 // 这是来自`WebFreak`在`Dwiki`上的示例代码

enum AVR_ARCH = 5; // MCU 的 AVR 架构

static if (AVR_ARCH >= 100) {
 enum SFR_OFFSET = 0x00;
} else {
 enum SFR_OFFSET = 0x20;
}

enum ubyte* MMIO_BYTE(ubyte memAddr) = cast(ubyte*) memAddr;
enum ubyte* SFR_IO8(ubyte ioAddr) = MMIO_BYTE!(ioAddr + SFR_OFFSET);

enum ubyte* PINB = SFR_IO8!(0x03);
enum ubyte* DDRB = SFR_IO8!(0x04);
enum ubyte* PORTB = SFR_IO8!(0x05);

extern(C) void main() {
  import core.volatile;

  volatileStore(DDRB, 0xFF);
    //端口所有B设置为输出

  // 我添加了延迟

  while (true) {
    volatileStore(PORTB, 0xFF);
    //端口所有B设置为高
    foreach(i; 0 .. 10)
        _delay(1000);
    volatileStore(PORTB, 0x00);
    //端口所有B设置为低
    foreach(i; 0 .. 20)
        _delay(1000);
  }
}

先,make文件:

# Makefile
$ cat Makefile
all:
        ldc2 delay.d -betterC -Oz -mtriple=avr -mcpu=atmega328p -Xcc=-mmcu=atmega328p -gcc=avr-gcc
        avr-objcopy -O ihex -R .eeprom delay delay.hex
        avrdude -F -V -c arduino -p ATMEGA328P -P /dev/ttyACM0 -b 115200 -U flash:w:delay.hex -C /opt/arduino/arduino-1.8.10/hardware/tools/avr/etc/avrdude.conf

请不要在最后一行的路径,再次安装arduino.
要运行它,请设置PATH为你的arduino安装,并运行make,如下所示:

PATH=/opt/arduino/arduino-1.8.10/hardware/tools/avr/bin:$PATH make

这编译D代码,然后把它复制arduino硬件并开始运行它.灯(及连接到引脚上的其他东西)闪烁.
如果查看上面链接的wiki页面,其中大部分内容很熟悉.我随意复制/粘贴.
需要注意的一些重要事项:
1,不能用extern(C)arduinoC的头文件中调用delay_ms,因为它是按内联函数定义的.库或目标文件中没有内联函数;你必须移植源.

WebFreak在此移植了源码,我解释下.
gccldc中的内联asm略有不同.这是文件中的_delay_loop_1:

void _delay_loop_1(uint8_t __count)
{
    __asm__ volatile (
        "1: dec %0" "\n\t"
        "brne 1b"
        : "=r" (__count)
        : "0" (__count)
    );
}

而,如下是D文件中:

import ldc.llvmasm;
// delay_basic.h中的移植
void _delay_loop_1(ubyte __count) {
//该模板参数是必需的,以避免
//`!Call.getType()->isVoidTy()&&"Badinlineasm!"'`断定失败.

    __asm!ubyte (
        "1: dec $0\n\tbrne 1b",
        "=r,0", (__count)
    );
}

asm不一样.在gcc中,它使用__asm__.在ldc中,它使用ldc.llvmasm.__asm.它们相似但不同:
1,gcc使用%0作为占位符.ldc使用了$0.
2,gcc使用冒号+神奇约束串.ldc使用函数的第二个参数.所有约束都必须在ldc用逗号分隔的串中.
3,gcc似乎会自动计算出大小.ldc不会.不能指定会触发编译器断定失败.我并不知道类型,但是让输入匹配似乎正确.
构建和部署过程都来自arduino工具,所以除了设置路径外,都与C一样.
我使用了-gcc,--link-internally要麻烦些.

我在这里使用了ldc,因为它在下载时开箱即用,无需自己构建.
内联汇编对这些控制器计时有些重要,因此能够做到这一点很酷.

相关文章:

  • 艺术类网站模板/网站建设推广服务
  • 做爰全过程免费网站/软文营销怎么写
  • wordpress 代码复制/网络推广seo怎么做
  • 免费微网站建设/广告公司的业务范围
  • 深圳代理记账报税公司/seo手机关键词排行推广
  • html5下载教程/宁波网站关键词优化排名
  • 将springboot项目部署到云服务器中,将vue项目部署到nginx中
  • 带你吃透Servlet核心编程下篇(完整图文教程)
  • Go语言详解
  • 初窥string(1)——string的基本使用
  • MyBatis的核心配置文件
  • 【SpringCloud学习笔记】Feign
  • 黑猫带你学UFS协议第8篇:UFS标志(Flags)和属性(Atrributes)详解
  • 你一定要知道的代码规范(进阶)
  • [Vue]插件
  • 大话西游服务端开服架设服务器搭建教程
  • 第三章Linux环境基础开发工具使用(yum+rzsz+vim+g++和gcc+gdb+make和Makefile+进度条+git)
  • C++(类与对象)是纸老虎吗?