移植arduino,让arduino集成环境支持 EK-LM3S811开发板-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 5549|回复: 3

移植arduino,让arduino集成环境支持 EK-LM3S811开发板

[复制链接]
发表于 2015-12-2 17:14 | 显示全部楼层 |阅读模式
本帖最后由 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调试器。
EK-LM3S811.jpg
硬件资源
·  CPU:Stellaris LM3S811 Cortex-M3,50MHz
64k flash   8K sram
·  板载用户按键和LED
·  复位按键和电源指示灯
·  Stellaris 外围驱动库, 为Stellaris 微控制器提供了便捷的初始化方法,编程以及外设控制
·  开发板集成StellarisI icdi USB调试器,支持CCS和MDK工具。
·  低成本的调试方案,开放原理图和调试固件,便于用户自己制作调试器
·  供电方式:USB供电

完成后的界面:
2.JPG

完成后的文件夹目录树:
1.jpg

内容较多,只能一步一步写,请耐心等待;




 楼主| 发表于 2015-12-2 23:20 | 显示全部楼层
移植过程悲喜交加,每每步入迷途时,万能的上帝总能引导我看到花明。

雄心壮志:尽管 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"

现在我们来看看这个文件:


[mw_shl_code=bash,true]#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 LOW  0x0

#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[P] )
#define digitalPinToBitMask(P)    ( digital_pin_to_bit_mask[P] )
#define digitalPinToTimer(P)      ( digital_pin_to_timer[P] )
#define analogInPinToBit(P)       (P)                            //add by hw
#define timerToAB(P)              ( timer_to_ab[P] )
#define timerToOffset(P)          ( timer_to_offset[P] )
#define timerToPinConfig(P)       ( timer_to_pin_config[P] )
#define digitalPinToADCIn(P)      (((P)<NUM_ANALOG_INPUTS)? digital_pin_to_analog_in[P]:NOT_ON_ADC)
#define portBASERegister(P)       ((volatile uint32_t *) port_to_base[P])
#define portDATARegister(P)       ((volatile uint32_t *)( port_to_base[P] + 0x3FC ))
#define portDIRRegister(P)        ((volatile uint32_t *)( port_to_base[P] + 0x400 ))
#define portIBERegister(P)        ((volatile uint32_t *)( port_to_base[P] + 0x408 ))
#define portIEVRegister(P)        ((volatile uint32_t *)( port_to_base[P] + 0x40C ))
#define portIMRegister(P)         ((volatile uint32_t *)( port_to_base[P] + 0x410 ))
#define portRISRegister(P)        ((volatile uint32_t *)( port_to_base[P] + 0x414 ))
#define portMISRegister(P)        ((volatile uint32_t *)( port_to_base[P] + 0x418 ))
#define portICRRegister(P)        ((volatile uint32_t *)( port_to_base[P] + 0x41C ))
#define portAFSELRegister(P)      ((volatile uint32_t *)( port_to_base[P] + 0x420 ))
#define portDR2RRegister(P)       ((volatile uint32_t *)( port_to_base[P] + 0x500 ))
#define portDR4RRegister(P)       ((volatile uint32_t *)( port_to_base[P] + 0x504 ))
#define portDR8RRegister(P)       ((volatile uint32_t *)( port_to_base[P] + 0x508 ))
#define portODRRegister(P)        ((volatile uint32_t *)( port_to_base[P] + 0x50C ))
#define portPURRegister(P)        ((volatile uint32_t *)( port_to_base[P] + 0x510 ))
#define portPDRRegister(P)        ((volatile uint32_t *)( port_to_base[P] + 0x514 ))
#define portSLRRegister(P)        ((volatile uint32_t *)( port_to_base[P] + 0x518 ))
#define portDENRegister(P)        ((volatile uint32_t *)( port_to_base[P] + 0x51C ))
/*#define portLOCKRegister(P)       ((volatile uint32_t *)( port_to_base[P] + 0x520 ))
#define portCRRegister(P)         ((volatile uint32_t *)( port_to_base[P] + 0x524 ))
#define portAMSELRegister(P)      ((volatile uint32_t *)( port_to_base[P] + 0x528 ))
#define portPCTLRegister(P)       ((volatile uint32_t *)( port_to_base[P] + 0x52C ))
#define portADCCTLRegister(P)     ((volatile uint32_t *)( port_to_base[P] + 0x530 ))
#define portMACTLRegister(P)      ((volatile uint32_t *)( port_to_base[P] + 0x534 ))
#define portPeriphID4Register(P)  ((volatile uint32_t *)( port_to_base[P] + 0xFD0 ))
#define portPeriphID5Register(P)  ((volatile uint32_t *)( port_to_base[P] + 0xFD4 ))
#define portPeriphID6Register(P)  ((volatile uint32_t *)( port_to_base[P] + 0xFD8 ))
#define portPeriphID7Register(P)  ((volatile uint32_t *)( port_to_base[P] + 0xFDC ))
#define portPeriphID0Register(P)  ((volatile uint32_t *)( port_to_base[P] + 0xFE0 ))
#define portPeriphID1Register(P)  ((volatile uint32_t *)( port_to_base[P] + 0xFE4 ))
#define portPeriphID2Register(P)  ((volatile uint32_t *)( port_to_base[P] + 0xFE8 ))
#define portPeriphID3Register(P)  ((volatile uint32_t *)( port_to_base[P] + 0xFEC ))
#define portCellID0Register(P)    ((volatile uint32_t *)( port_to_base[P] + 0xFF0 ))
#define portCellID1Register(P)    ((volatile uint32_t *)( port_to_base[P] + 0xFF4 ))
#define portCellID2Register(P)    ((volatile uint32_t *)( port_to_base[P] + 0xFF8 ))
#define portCellID3Register(P)    ((volatile uint32_t *)( port_to_base[P] + 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
[/mw_shl_code]

其中 188~205代码在LM3s811中无用,直接/* */掉了。

下次引脚(pin)定义文件:pins_energia.h(待续)
发表于 2015-12-6 19:40 | 显示全部楼层
lz研究的很深入,希望能放出完整的代码。
发表于 2016-1-27 16:43 | 显示全部楼层
TI好几个芯片都有Arduino core lib
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 10:39 , Processed in 0.350675 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表