移植arduino,让arduino集成环境支持 EK-LM3S811开发板
本帖最后由 huaweiwx 于 2015-12-2 18:57 编辑初来本坛,献上一个厚礼:如何移植建立一个arduio开发环境,来支持目前arduino官方不支持的芯片和板子。
序:曾经在网上看到一个arm板子,EK-LM3S811,8元白菜价处理; 一个带板载调试器的板子,且TI管网有完整的资料和库的支持,便买了个玩玩,为了程序的可移植性,目前无论的avr还是arm,我均在arduino下开发,对这个拿来玩玩的板子,我也不想重新写一大堆和硬件有关的代码,以后在其它目标MCU上还要重写,便觉得要是像arduino支持的芯片那样:操作串口直接用Serial.begin(xxxx), 操作端口 直接用digitalRead(xx)那多爽?
结果是,本来不想和TI ARM系列芯片的寄存器和库打交道,却偏偏深入对这些研究了一番;最终弄成了一个让 Arduino支持的 LM3S811 环境;
本着arduino的开源精神,我也将此全部开源奉献给喜欢arduino的朋友,事实上要让arduino支持那些目前官方不支持的 AVR或ARM芯片,并非想象的那么难!
EK-LM3S811 简介(摘自网络):
EK-LM3S811评估板是英蓓特公司新推出的基于 TI LM3S811处理器的低成本调试方案。评估板处理器采用的是LM3S811 ,内核Cortex-M3,主频50M,板载Stellaris icdi USB调试器。
硬件资源·CPU:Stellaris LM3S811 Cortex-M3,50MHz64k flash 8K sram·板载用户按键和LED·复位按键和电源指示灯·Stellaris 外围驱动库, 为Stellaris 微控制器提供了便捷的初始化方法,编程以及外设控制·开发板集成StellarisI icdi USB调试器,支持CCS和MDK工具。·低成本的调试方案,开放原理图和调试固件,便于用户自己制作调试器·供电方式:USB供电
完成后的界面:
完成后的文件夹目录树:
内容较多,只能一步一步写,请耐心等待;
移植过程悲喜交加,每每步入迷途时,万能的上帝总能引导我看到花明。
雄心壮志:尽管 arduino已支持arm,包括stm32系列和ATSAM3X8E(arduino Duo),开始想仿照上述系列来改写,粗略看了一下,头都晕了,每个厂商的芯片有其自己的驱动库,如不用驱动,则不但需要了解两种不同芯片的这些寄存器,按功能来改写;如用库,则要找出这些对应的库功能。反正是工程浩大,想想也是,要是简单的话,早就有许多移植版本了。
“天道助勤”:当我想放弃的时候,我在网上发现TI有个类似arduino的开发环境 energia,尽管不直接lm3s811,但毕竟是同一公司产品,驱动库构架和调用方式都是一样,我就选用这个系统的开源部分内容开始我的工作。
放弃energia: 我先搭了个构架,就是在空的core中写两个程序startup.c 和拷贝一个直接寄存器操作的example代码(blink)尝试在energia下编译,看看是否能成,结果打了我一个闷棍,发现在eneria下无法正确生产cortex-m3核心的代码,energia环境下不像 arduno有个platform.txt来定义如何生成代码,规则是内定的(也许我没找到在何处定义的)。
再次尝试:仿照stm32的GCC生成规则,但按energia中的实现方法,移植energia针对LM4F的代码。
又受挫折:并发现:ti许多的arm芯片竟然包含一个内部的rom,把底层驱动的很多核心代码封装好,并提供了一个调用地址定义头文件,而恰恰LM3S811这个廉价芯片是个不含rom的。显然自己不可能写一个兼容rom功能的库!
船到桥头:发现ti提供了一个对应的当无rom或rom功能使替代方案,只要将所有rom调用函数 ROM_XXXXX改为MAP_XXXXXX,这样方便了,
查找替换几分钟就搞定。
要调试核心程序,定义文件是必不可少的,首先是energia.h
energia中也有个arduino.h,其中只有一行代码:
#include ”energia.h"
现在我们来看看这个文件:
#ifndef Energia_h
#define Energia_h
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
#include "itoa.h"
#include "part.h"
#include <avr/dtostrf.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#if defined(PART_LM3S811)
//#include "lm3s811.h"
#else
#error "**** No PART defined or unsupported PART ****"
#endif
#include "binary.h"
#include "hw_types.h"
#include "sysctl.h"
#include "hw_nvic.h"
#include "gpio.h"
#ifdef __cplusplus
extern "C"{
#endif
#define NOT_A_PORT 0
#define NOT_A_PIN 0
#define NOT_ON_TIMER 0
#define NOT_ON_ADC 0x10
#define CHANGE 4
#define FALLING 3
#define RISING 2
#define HIGH 0x1
#define LOW0x0
#define LSBFIRST 0
#define MSBFIRST 1
#define INPUT 0x0
#define OUTPUT 0x1
#define INPUT_PULLUP 0x2
#define INPUT_PULLDOWN 0x3
#define SPI_LAST 0
#define SPI_CONTINUE 1
#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
#define DEG_TO_RAD 0.017453292519943295769236907684886
#define RAD_TO_DEG 57.295779513082320876798154814105
#define PA 1
#define PB 2
#define PC 3
#define PD 4
#define PE 5
#define PF 6
#define PG 7
#define PH 8
#define PJ 9
#define PK 10
#define PL 11
#define PM 12
#define PN 13
#define PP 14
#define PQ 15
#define PR 16
#define PS 17
#define PT 18
#define TIMA 0
#define TIMB 8
#if defined(__LM3S811__)
#define T0A 0
#define T0B 1
#define T1A 2
#define T1B 3
#define T2A 4
#define T2B 5
#define TIMER0 0
#define TIMER1 1
#define TIMER2 2
#endif
typedef uint8_t boolean;
typedef uint8_t byte;
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x))
#define interrupts() IntMasterEnable()
#define noInterrupts() IntMasterDisable()
#define clockCyclesPerMicrosecond() (F_CPU / 1000000L )
//#define clockCyclesPerMicrosecond() ( 80000000L / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
typedef unsigned int word;
#define bit(b) (1UL << (b))
void init(void);
void setup(void);
void loop(void);
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
void pinMode(uint8_t, uint8_t);
void digitalWrite(uint8_t, uint8_t);
int digitalRead(uint8_t);
void digitalToggle(uint8_t pin);//add by huawei
uint16_t analogRead(uint8_t);
void analogWrite(uint8_t, int);
void analogReference(uint16_t);
void analogFrequency(uint32_t);
void analogResolution(uint16_t);
void delay(uint32_t milliseconds);
/* void sleep(uint32_t milliseconds);
void sleepSeconds(uint32_t seconds);
void suspend(void);
extern volatile boolean stay_asleep;
#define wakeup() { stay_asleep = false; }
*/
void attachInterrupt(uint8_t, void (*)(void), int mode);
void detachInterrupt(uint8_t);
extern const uint8_t digital_pin_to_timer[];
extern const uint8_t digital_pin_to_port[];
extern const uint8_t digital_pin_to_bit_mask[];
extern const uint32_t timer_to_offset[];
extern const uint8_t timer_to_ab[];
extern const uint32_t timer_to_pin_config[];
extern const uint32_t port_to_base[];
extern const uint32_t digital_pin_to_analog_in[];
#define digitalPinToPort(P) ( digital_pin_to_port )
#define digitalPinToBitMask(P) ( digital_pin_to_bit_mask )
#define digitalPinToTimer(P) ( digital_pin_to_timer )
#define analogInPinToBit(P) (P) //add by hw
#define timerToAB(P) ( timer_to_ab )
#define timerToOffset(P) ( timer_to_offset )
#define timerToPinConfig(P) ( timer_to_pin_config )
#define digitalPinToADCIn(P) (((P)<NUM_ANALOG_INPUTS)? digital_pin_to_analog_in:NOT_ON_ADC)
#define portBASERegister(P) ((volatile uint32_t *) port_to_base)
#define portDATARegister(P) ((volatile uint32_t *)( port_to_base + 0x3FC ))
#define portDIRRegister(P) ((volatile uint32_t *)( port_to_base + 0x400 ))
#define portIBERegister(P) ((volatile uint32_t *)( port_to_base + 0x408 ))
#define portIEVRegister(P) ((volatile uint32_t *)( port_to_base + 0x40C ))
#define portIMRegister(P) ((volatile uint32_t *)( port_to_base + 0x410 ))
#define portRISRegister(P) ((volatile uint32_t *)( port_to_base + 0x414 ))
#define portMISRegister(P) ((volatile uint32_t *)( port_to_base + 0x418 ))
#define portICRRegister(P) ((volatile uint32_t *)( port_to_base + 0x41C ))
#define portAFSELRegister(P) ((volatile uint32_t *)( port_to_base + 0x420 ))
#define portDR2RRegister(P) ((volatile uint32_t *)( port_to_base + 0x500 ))
#define portDR4RRegister(P) ((volatile uint32_t *)( port_to_base + 0x504 ))
#define portDR8RRegister(P) ((volatile uint32_t *)( port_to_base + 0x508 ))
#define portODRRegister(P) ((volatile uint32_t *)( port_to_base + 0x50C ))
#define portPURRegister(P) ((volatile uint32_t *)( port_to_base + 0x510 ))
#define portPDRRegister(P) ((volatile uint32_t *)( port_to_base + 0x514 ))
#define portSLRRegister(P) ((volatile uint32_t *)( port_to_base + 0x518 ))
#define portDENRegister(P) ((volatile uint32_t *)( port_to_base + 0x51C ))
/*#define portLOCKRegister(P) ((volatile uint32_t *)( port_to_base + 0x520 ))
#define portCRRegister(P) ((volatile uint32_t *)( port_to_base + 0x524 ))
#define portAMSELRegister(P) ((volatile uint32_t *)( port_to_base + 0x528 ))
#define portPCTLRegister(P) ((volatile uint32_t *)( port_to_base + 0x52C ))
#define portADCCTLRegister(P) ((volatile uint32_t *)( port_to_base + 0x530 ))
#define portMACTLRegister(P) ((volatile uint32_t *)( port_to_base + 0x534 ))
#define portPeriphID4Register(P)((volatile uint32_t *)( port_to_base + 0xFD0 ))
#define portPeriphID5Register(P)((volatile uint32_t *)( port_to_base + 0xFD4 ))
#define portPeriphID6Register(P)((volatile uint32_t *)( port_to_base + 0xFD8 ))
#define portPeriphID7Register(P)((volatile uint32_t *)( port_to_base + 0xFDC ))
#define portPeriphID0Register(P)((volatile uint32_t *)( port_to_base + 0xFE0 ))
#define portPeriphID1Register(P)((volatile uint32_t *)( port_to_base + 0xFE4 ))
#define portPeriphID2Register(P)((volatile uint32_t *)( port_to_base + 0xFE8 ))
#define portPeriphID3Register(P)((volatile uint32_t *)( port_to_base + 0xFEC ))
#define portCellID0Register(P) ((volatile uint32_t *)( port_to_base + 0xFF0 ))
#define portCellID1Register(P) ((volatile uint32_t *)( port_to_base + 0xFF4 ))
#define portCellID2Register(P) ((volatile uint32_t *)( port_to_base + 0xFF8 ))
#define portCellID3Register(P) ((volatile uint32_t *)( port_to_base + 0xFFC ))
*/
// Implemented in wiring.c
void delayMicroseconds(unsigned int us);
unsigned long micros();
unsigned long millis();
void timerInit();
void registerSysTickCb(void (*userFunc)(uint32_t));
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
#include "WCharacter.h"
#include "WString.h"
#include "HardwareSerial.h"
uint16_t makeWord(uint16_t w);
uint16_t makeWord(byte h, byte l);
#define word(...) makeWord(__VA_ARGS__)
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
void tone(uint8_t _pin, unsigned int frequency);
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration);
void noTone(uint8_t _pin);
// WMath prototypes
long random(long);
long random(long, long);
void randomSeed(unsigned int);
long map(long, long, long, long, long);
#endif
#include "pins_energia.h"
#endif
其中 188~205代码在LM3s811中无用,直接/* */掉了。
下次引脚(pin)定义文件:pins_energia.h(待续)
lz研究的很深入,希望能放出完整的代码。 TI好几个芯片都有Arduino core lib
页:
[1]