單片機編程能用MAC么?

單片機編程能用MAC么?

(至今還沒有接觸 單片機)


我在mac下經常做STM32和AVR的開發,可以分享一下經驗。

AVR和STM32的開發原則上用的都是GCC編譯器。在常見的Linux發行版,如Debian、Ubuntu里都有對應的軟體包,在Mac下則可以用MacPorts來安裝,STM32對應的是arm-none-eabi-gcc,AVR對應的是avr-gcc。

除了編譯器以外,還需要一些輔助的軟體庫才能編譯出來可用的固件。對AVR,需要的是avr-libc。其在1.8版本以後有不兼容修改,所以建議看最新的文檔,已有出版的書籍大多是基於舊版本的,這一點要小心。AVR的配置相對簡單,直接編譯連接就是了。網上有很多教程。文後有我用scons構建AVR程序的python腳本。燒寫軟體則可以用avrdude。

STM32的開發則相對複雜,其GCC編譯器與很多人在Windows下所學的Keil等有較大的區別,且文檔不是那麼的完善,所以會痛苦一些。STM32除了編譯器外,還需要連接腳本,即.ld文件,每個晶元系列都有不同的文件,晶元內外設還需要對應的驅動,可以用STM32的標準外設庫,我是用3.5版的stdperiphlib。燒寫軟體使用OpenOCD。

構建工具,可以考慮用相對簡單的Makefile。不過Makefile的能力所限也是眾所周知,可以酌情配置更為強大的構建工具,比如CMake。而我因為對Python較為熟悉,所以是用scons的,因為可以用上強大的Python,所以能實現更多功能。比如燒寫時直接調用OpenOCD的一系列命令。

AVR的scons配置腳本:

# -*- coding: UTF-8 -*-

# File: avrbase.py

# Date: 2013-07-13

# Author: harry

"""

AVR的基礎編譯支持

"""

import os

env=Environment()

env.Replace(CC="avr-gcc")

env.Replace(AS="avr-as")

if SRC_LIST[0].endswith(".c"): #C程序的鏈接

env.Append(LINKFLAGS="-mmcu=$MCU")

elif SRC_LIST[0].endswith(".s"):#彙編程序的鏈接

env.Replace(LINK="avr-ld")

env.Replace(MCU=MCU)

env.Replace(PROGRAM=PROGRAM)

env.Append(CFLAGS="-Wall")

env.Append(CFLAGS="-Os")

env.Append(CFLAGS="-mmcu=$MCU")

#env.Append(ASFLAGS="-Wall") #會導致列印出彙編代碼

env.Append(ASFLAGS="-mmcu=$MCU")

env.AppendENVPath("PATH","/opt/local/bin")

OBJ_LIST=[]

for src in SRC_LIST:

obj=env.Object(src)

OBJ_LIST.append(obj)

#elf_main=env.Command("${SOURCE.base}.elf",obj_main,"""${LD} -o $TARGET $SOURCE""")

elf_main=env.Program("${PROGRAM}.elf",OBJ_LIST)

hex_main=env.Command("${PROGRAM}.hex",elf_main,"""avr-objcopy -j .text -j .data -O ihex $SOURCE $TARGET""")

size_main=env.Command(None,elf_main,"""avr-size $SOURCE""")

if "write" in COMMAND_LINE_TARGETS:

cmd="""avrdude -c usbasp -p $MCU -F -e -U flash:w:$SOURCE"""

if os.uname()[0]=="Linux":

cmd="sudo "+cmd

env.Command("write",[hex_main,size_main],cmd)

if "trans" in COMMAND_LINE_TARGETS:

cmd="""avrdude -c usbasp -p $MCU -F -t"""

if os.uname()[0]=="Linux":

cmd="sudo "+cmd

env.Command("trans",None,cmd)

if "dump" in COMMAND_LINE_TARGETS:

env.Command("dump",elf_main,"""avr-objdump -d $SOURCE &> ${SOURCE.base}.s""")

STM32的scons配置腳本則複雜的多,並且分為了好幾個文件。用以引用的第一個文件common.py如下:

# -*- coding: UTF-8 -*-

# File: common.py

# Date: 2014-01-26

# Author: gashero

"""

對各個板子和平台共用的變數

"""

import os

import platform

env=Environment()

if platform.system()=="Darwin":

CROSS_COMPILE="arm-none-eabi-"

elif platform.system()=="Linux":

CROSS_COMPILE="arm-none-eabi-"

#env.Append(CFLAGS="-Wl,--print-gc-sections")

#env.Append(CFLAGS="-Wl,-s") #會導致反彙編丟失函數信息

#env.Append(CFLAGS="-Wl,--build-id=none")

else:

raise RuntimeError("Unknow platform.system()=%s"%repr(platform.system()))

env.Replace(CC=CROSS_COMPILE+"gcc")

env.Replace(AR=CROSS_COMPILE+"ar")

env.Replace(AS=CROSS_COMPILE+"as")

env.Replace(RANLIB=CROSS_COMPILE+"ranlib")

env.Replace(LD=CROSS_COMPILE+"ld")

env.Replace(SIZE=CROSS_COMPILE+"size")

env.Replace(OBJCOPY=CROSS_COMPILE+"objcopy")

env.Replace(OBJDUMP=CROSS_COMPILE+"objdump")

env.AppendENVPath("PATH","/opt/local/bin")

env.Append(CFLAGS="-I.")

#env.Append(CFLAGS="-g") #代碼段一樣長度,但多了個.debug_info段

env.Append(CFLAGS="-Wall")

env.Append(CFLAGS="-mcpu=${MCU}")

env.Append(CFLAGS="-fno-common")

env.Append(CFLAGS="-nostdlib") #似乎不必要

#env.Append(CFLAGS="-march=armv7-m") #似乎不必要,且Cortex-M0不能用

env.Append(CFLAGS="-ffunction-sections") #如下3行一起優化了不少代碼空間,如一次6020=&>2164

env.Append(CFLAGS="-fdata-sections")

env.Append(CFLAGS="-Wl,--gc-sections")

env.Append(CFLAGS="-Os") #優化代碼大小,如一次2164=&>1424

env.Append(CFLAGS="-mthumb") #僅供Cortex-M系列使用

env.Append(CFLAGS="-DUSE_STDPERIPH_DRIVER")

env.Append(CFLAGS="-DHSE_VALUE=%d"%HSE_VALUE)

env.Append(ASFLAGS="-mcpu=${MCU}")

#env.Append(ASFLAGS="-march=armv7-m") #僅供ARM-V7M系列

env.Append(ASFLAGS="-mthumb")

env.Replace(MCU=MCU)

env.Replace(PROGRAM=PROGRAM)

env.Replace(PERIPH_SRC_PATH=PERIPH_SRC_PATH)

env.Replace(LD_SCRIPT=LD_SCRIPT)

PERIPH_SRC_LIST=os.listdir(PERIPH_SRC_PATH)

PERIPH_SRC_LIST=filter(lambda fn:fn not in (".hg",".svn"),PERIPH_SRC_LIST)

PERIPH_SRC_LIST=map(lambda srcpath:os.path.join(

PERIPH_SRC_PATH,srcpath),PERIPH_SRC_LIST)

src_to_build=lambda srcpath:os.path.join("build",

os.path.splitext(os.path.split(srcpath)[-1])[0])

#編譯標準外設

PERIPH_OBJ_LIST=[]

for src in PERIPH_SRC_LIST:

obj=env.Object(src_to_build(src),src)

PERIPH_OBJ_LIST.append(obj)

stdperiph=env.StaticLibrary("stdperiph",PERIPH_OBJ_LIST)

ELF_CMD="""${CC} ${CFLAGS} -mthumb -mcpu=${MCU} -nostartfiles -T${LD_SCRIPT} -Wl,-Map,${PROGRAM}.map -o ${TARGET} ${SOURCES}"""

用以倍後部引用的燒寫相關支持命令readwrite.py內容如下:

# -*- coding: UTF-8 -*-

# File: readwrite.py

# Date: 2013-05-07

# Author: gashero

"""

需要編譯出結果才能執行的部分

"""

import time

import socket

import subprocess

def flash_write(fn_image,fmt,addr):

"""連接OpenOCD燒寫指定鏡像"""

assert fmt in ("elf","hex","bin")

cmdlist=(

"reset",

"halt",

"flash write_image erase "%s" %s %s"%(fn_image,addr,fmt),

"reset",

"poll",

)

cs=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

cs.connect(("127.0.0.1",4444))

for cmd in cmdlist:

cs.send(cmd+"
")

time.sleep(0.5)

data=cs.recv(1024)

print data

cs.close()

return

def flash_swrite(fn_image,dev_serial):

"""使用串口燒寫鏡像"""

ff=open(fn_image)

img=ff.read()

ff.close()

left=len(img)%4

if left:

img+="xff"*(4-left)

ff=open(fn_image,"w")

ff.write(img)

ff.close()

assert len(img)%4==0

cmd="stm32flash -w %s -v -g 0x00 %s"%(

fn_image,dev_serial)

assert 0==os.system(cmd)

return

OBJ_LIST=[]

for src in SRC_LIST:

obj=env.Object(src_to_build(src),src)

OBJ_LIST.append(obj)

elf_main=env.Command("${PROGRAM}.elf",OBJ_LIST+[stdperiph,],ELF_CMD)

hex_main=env.Command("${SOURCE.base}.hex",elf_main,"${OBJCOPY} -Oihex ${SOURCE} ${TARGET}")

bin_main=env.Command("${SOURCE.base}.bin",elf_main,"${OBJCOPY} -Obinary ${SOURCE} ${TARGET}")

size_main=env.Command(None,elf_main,"${SIZE} ${SOURCE}")

env.Replace(HEX_MAIN=hex_main)

env.Replace(ELF_MAIN=elf_main)

env.Replace(BIN_MAIN=bin_main)

if "write" in COMMAND_LINE_TARGETS:

#env.Command("write",hex_main,"""echo "ha #env.Command("write",elf_main,"""echo "ha #env.Command("write",elf_main,"""echo "reset;ha env.Command("write",elf_main,"""echo """"")

flash_write(env["ELF_MAIN"][0],"elf","0x00")

#flash_write(env["BIN_MAIN"][0],"bin","0x08000000")

if "swrite" in COMMAND_LINE_TARGETS:

env.Command("swrite",bin_main,"""echo """"")

flash_swrite(str(env["BIN_MAIN"][0]),str(env["DEV_SERIAL"]))

if "read" in COMMAND_LINE_TARGETS:

env.Command("read",None,"""echo "ha

if "dump" in COMMAND_LINE_TARGETS:

env.Command("dump",elf_main,"""${OBJDUMP} -D ${SOURCE} &> ${SOURCE.base}.lst""")

if "oocd" in COMMAND_LINE_TARGETS:

OOCD_SCRIPT_PATH=[

"/opt/local/share/openocd/scripts",

"/usr/local/share/openocd/scripts",

"/usr/share/openocd/scripts",

]

for pathname in OOCD_SCRIPT_PATH:

if os.path.exists(pathname):

optionlist=[]

for confpath in OOCD_CONF_PATH:

optionlist.append("-f "+os.path.join(pathname,confpath))

env.Command("oocd",None,"openocd "+" ".join(optionlist))

具體的每個晶元,或者開發板,應該有獨立的配置,包括其連接腳本等。比如x寶上容易買到的源地科技的STM32F030開發板,我將其命名為vg030f4p6.py,其內容如下:

# -*- coding: UTF-8 -*-

# File: vg030f4p6.py

# Date: 2014-09-22

# Author: harry

"""

STM32F030F4P6開發板,14.8元

http://vcc-gnd.com的產品

16KB Flash,4KB SRAM,VL線。

默認晶振8MHz,系統頻率48MHz

沒有任何板載器件

"""

HSE_VALUE=8000000

MCU="cortex-m0"

print "ARMROOT=",ARMROOT

LD_SCRIPT=os.path.join(ARMROOT,"_stm32_board/stm32f030f4.ld")

BOARD_SRC_LIST=[]

BOARD_SRC_LIST+=[

os.path.join(ARMROOT,"_stm32_board/startup_stm32f030.s"),

os.path.join(ARMROOT,"_stm32_board/system_vg030f4p6.c"),

#也許還有BSP的代碼

]

PERIPH_SRC_PATH=os.path.join(ARMROOT,"_stm32_Libraries/STM32F0xx_StdPeriph_Driver/src")

exec(open(os.path.join(ARMROOT,"_stm32_board/common.py"),"rU").read())

env.Append(CFLAGS="-I"+os.path.join(ARMROOT,

"_stm32_Libraries/CMSIS/Device/ST/STM32F0xx/Include"))

env.Append(CFLAGS="-I"+os.path.join(ARMROOT,

"_stm32_Libraries/CMSIS/Include"))

env.Append(CFLAGS="-I"+os.path.join(ARMROOT,

"_stm32_Libraries/STM32F0xx_StdPeriph_Driver/inc"))

env.Append(CFLAGS="-I"+os.path.join(ARMROOT,

"_stm32_board"))

env.Append(CFLAGS="-DSTM32F030")

env.Append(CFLAGS="-DVG030F4P6")

OOCD_CONF_PATH=[

#"interface/openjtag.cfg", "target/stm32f1x.cfg",

#"interface/jlink.cfg", "target/stm32f1x.cfg",

"interface/stlink-v2.cfg", "target/stm32f0x_stlink.cfg",

]

我也不想貼這一大堆代碼。怎奈這也是我搞AVR9年來,STM32的5年來一步一坑積累而來,其中艱辛難以言表,不分享出來實在可惜。

基於如上的工具,我在Mac下,用vim編輯器,scons構建,寫了50+個AVR相關的小項目,大部分不超過1000行代碼。40+個STM32的小項目,規模會略大,畢竟標準外設庫寫代碼特別啰嗦,但可寫出的功能就豐富了許多了。


虛擬機的就不說了,作為一個超級愛折騰的人,我們來直接在Mac上搞一把arm開發。

---------------------------------

最近在搞ARM9,也是在mac(freeBSD)的終端上編譯u-boot和linux kernal,既然ARM9都可以,為什麼STM32這種單片機不可以?

Seeger家(jlink的廠家)出了一個類似KEIL的IDE,牛逼之處在於可以直接打開IAR和KEIL的工程(*.uvprojx) 並且有win/linux/mac三個平台版本SEGGER - The Embedded Experts

特性:

  • Windows, Mac OS X and Linux support
  • Powerful Project Manager, even for huge projects
  • Advanced first-class Editor
  • Package-based Project Generator for all common microcontrollers
  • Pre-built C/C++ Compiler, GCC and LLVM included for an immediate start
  • Royalty-free ANSI / ISO C compliant C library for embedded systems
  • Feature-packed Debugger with seamless J-Link integration

配合Jlink的mac版本驅動:SEGGER - The Embedded Experts

有時間搞一發看看


建議不要用Mac做硬體開發。

寫軟體是第一個難題,很多MCU的開發工具都沒有。

第二個難題是很多調試工具也沒有。

Mac更適應Web開發和設計。


不想折騰的話,使用虛擬機是一種比較簡單的方法。另外,因為 OS X 是 UNIX 操作系統,大多數用於用於單片機開發的開源工具,都可以方便地在 OS X 上運行。

Toolchains:

  • SDCC: 用於 8051, Z80, STM8 等單片機

  • GCC: 支持 AVR, ARM (包括 Cortex-M 和 Cortex-R 系列,例如 STM32), MSP430 等

下載、燒寫、調試工具:

  • stcflash, gSTC-ISP: STC 單片機下載工具,另外對於 STC 最新的 IAP 系列,應該可以自己設計通信協議,自己編寫 Bootloader 與下載工具,實現 ISP 下載

  • AVRDUDE: AVR 與 Atmel 8051 單片機的下載工具
  • J-Link: Segger 官方提供驅動和相關工具,在官網就能找到
  • ST-Link: 可使用開源工具 (texane/stlink · GitHub), 用 Homebrew 安裝即可
  • Open On-Chip Debugger: 開源的片上調試工具,支持 J-Link, ST-Link, CMSIS-DAP, ULINK 等,支持多種單片機和 FPGA

模擬器:

  • Qemu STM32: 支持 STM32 的 QEMU

IDE:

  • Arduino: 支持 Arduino (AVR, ARM, x86), 通過修改配置文件還可以支持其他 AVR 板,也可在 Boards Manager 中添加對 STM32, ESP8266 等的支持

  • Energia: 支持 TI 公司的單片機,包括 MSP430, ARM Corterx-M, CC3200 Wi-Fi SoC 等

  • maple-ide: 支持 Maple STM32 開發板

  • mbed: ARM mbed 開發板的 Web IDE

  • embedXcode: 將 Xcode 擴展成單片機開發環境,支持多種單片機
  • Eclipse: 可安裝擴展程序,從而支持其他單片機

    • 對於 STM32,可參考之前寫的這篇博文:使用 Eclipse 和 ARM GCC 搭建 STM32 開發環境
  • Simplicity Studio: Silicon Labs 官方 IDE,支持 C8051F, EFM8, EFM32 單片機
  • PlatformIO: 跨平台硬體開發工具,支持 Arduino, mbed, esp8266, stm32 等,包含編譯器、燒寫工具、串口監視器等一系列功能。並提供 Atom 插件 (PlatformIO IDE).


當然可以。

裝個Parallels Desktop虛擬機,再裝個Windows(我還裝了個ubuntu

Mac OS X和windows無縫切換不要太爽,所有軟體基本都能用到。(目前唯一遇到虛擬機上不能運行的是泡泡堂

而且最近正好在學單片機。發幾張圖。

J-Link

usb-串口數據線

虛擬機下windows8.1通過keil開發stm32

OS X 10.11

最後總結下:

優點:1.四指一滑能夠瞬間再OS X和windows間切換,多!么!炫!酷!

2.在OS X下主要用Xcode,Final Cut Pro X, office 2016, 看pdf, 瀏覽網路,聽歌等(續航時間長,發熱小。windows下主要用Keil, CCS, Porteus, Multisim等開發軟體(windows下才有

缺點:1.開了虛擬機後發熱量比只用OS X大,但是在可接受範圍,比看flash視頻熱量小的多。

2.學單片機的時候曾經因為虛擬機路徑問題出bug,找了很久。解決方法是不要把文件夾放桌面而放c盤根目錄下(坑爹吧

希望有幫助吧


我就說一句,萬一你的破板子把電腦主板xx了,你會不會哭


單純編譯什麼的沒問題,sdcc編譯器支持MacOS X。下載過程略費事,開源的stc-isp下載工具是python寫的運行沒問題,只是支持的STC型號受限。

現在用stcgal,似乎支持的晶元多了些,自己去github下載吧。


莫非題主是想問在MAC OS系統上能否做單片機開發?

答案是:可以

拿mega舉個例子

ATMEL沒有發布MAC OS版的AVR STUDIO,難道沒辦法開發么?但所謂的avr studio不過是一個有著華麗界面的(6.0 用上了visual studio的外殼,真是華麗的不得了)AVR-gcc罷了。。所以source forge上找個avr-gcc(這個是有OS版的),搭配一款用的順手的編輯器就可以開發了。(subline 不錯)

其餘c51,ARM同理

總而言之,你需要的是只是編譯器而已。。

但是!!!!

盜版的jtag,jlink想在MAC OS上跑起來,那是真的好難啊。。在OS上燒錄也好難啊。。所以還是裝WINDOWS 吧。。


真的沒啥問題


可行的,你搜一下(OpenOCD/Official Driver)+Eclipse+CDT+ARM-CC+STM32+(ST-LINK/J-LINK)這一組關鍵詞,有詳細的教程。

當然問題也很明顯,主要是以下幾個方面:

1.如果把SWD介面的SWO引腳remap成了其他功能,所以需要用一個USB轉UART的小板子來讀取STM32的UART口輸出,這個時候就體現出windows的優越性了:驅動隨便找個inf文件就能想怎麼用就怎麼用了,超級終端/putty/COMDBG/單片機開發助手/STC-ISP,想用哪個就用哪個。

如果我需要通過SPI對CSR的藍牙晶元燒錄,那個軟體也是沒有mac的驅動的= =

(就是各種非規範的國內生產的小USB配件,不提供mac下的驅動)

2.如果需要開發一個批量燒錄的軟體,ST-LINK如果要進行下載軟體的二次開發的話官方的ST Visual Programmer是沒有mac版本的,那個套件只給windows設計了。

3.如果你想要開發設備的驅動,比方說STM32轉USB CDC之類的,mac下調試沒有windows下那麼好用的分析軟體,比方說bus hound和usb trace之類的。還有,上位機常式缺失可能讓你折騰很久還不知道到底是上位機還是下位機的問題。

4.邏輯分析儀,不管是國產的還是國外的,除了saleae那個應該都是沒有mac驅動的。

5.我不知道AD、Eagle、Multisim之類的軟體在Mac下有沒有對應的版本,不過公司採購的時候一般都是直接採購的windows版本,這樣統一平台、統一品類,方便談價格,這種授權一般都是作為公司資產入賬的,所以不可能專門為你買一個Mac版本的,等你離職這個Mac授權誰用?

——綜上所述,驅動不全帶來的麻煩導致你開發環境和使用環境完全不能統一,因此開發效率極其底下。嵌入式平台對windows的強依賴使得在Mac下開發等於自絕於人民,強烈建議不要這麼用。

我個人是直接用的C-Lion+STM32-Nucleo+embedded st-link,體感不是很好,建議還是不要瞎浪了,還是走OpenOCD+Eclipse+ST-LINK的流派吧。

windows下的Keil套件一鍵式安裝,只要知道next鍵怎麼按就能隨便安裝,除了版權之外基本上沒有問題。

說到版權,發一張一個朋友的公司收到的郵件哈哈哈哈,ARM公司這個太狠辣


據我所知,MAC裝WIN7是可以的……但是調試的時候可能會有莫名其妙的編程器bug。


可以,我真是服了在Mac上裝虛擬機,再裝windows做開發的。放著這麼牛逼的BSD系統不用起來,真是糟蹋錢。


據我了解目前也就arduio 可以


應該不能,MacOS我掌握的情況是一個比較封閉的操作系統。移植需要MacOS公開底層硬體介面。

而且從源代碼和版權的角度看,MacOS並非一個免費的操作系統,蘋果從版權的考慮也不會公開源代碼,一旦源代碼不公開,則無法在另一個平台上編譯,從而得到bin。從而不可能移植。


怎麼把程序下載到板子上是個問題


什麼系列的?


看型號了,編譯器倒是好解決,關鍵下載軟體不好弄。


Ti 的CCS也有Mac版 雖說是beta 使用起來還是沒問題的,畢竟基於eclipse。但是uniflash至今未推出Mac版,雖然Ti說已經計劃推出。


不是不可以,但你可能會面臨資料匱乏的問題。

起碼去年我上單片機課程的時候是沒找著Mac下的燒寫辦法的。


當然可以,我就用mac做stm32.

無非就是gcc,openocd,gdb,make,libusb這些東西嘛,就是要寫linkscrypt,makefile.就是gdb不好使,調試時還是keil比較好用

所以呢,可不可以,那當然是可以了,好不好用就是另一回事了


推薦閱讀:

看書自學編程書後的習題多數都敲不出來怎麼辦?
結構體定義時不寫結構體名會有什麼影響嗎?
C/C++中switch語句為什麼匹配到標籤後不跳出?
怎麼理解 P 問題和 NP 問題?
FAQ-開發時需要先完成全部詳細設計/類圖嗎,如果需要那要詳細到什麼程度?

TAG:Mac | macOS應用 | 編程語言 | 編程 | 單片機 |