盒子
盒子
文章目录
  1. 在gentoo上设置开发环境
  2. last but not least

在Gentoo下开发Launchpad MSP430程序

同学给我了片申请到的MSP-EXP430G2单片机玩。

从来没有玩过单片机,虽然本科专业还开设了一门叫做单片机的课程,课上完了我也没见到单片机是什么样的,当然,我也没去过几次。研究生阶段选修了一门嵌入式系统设计的课程,只记的老师拿着ppt讲的吐沫星子飞起,似乎ppt上有图,最后却还是没注意单片机是什么样的。

几天前第一次在工地上见到了单片机,一个同学在树莓派的基础上不停假设外设,当时他去采购了一大批物资其中就有一小块单片机。当时一个师兄拿着给我说:这个是单片机。我第一次知道,噢~原来这就是单片机。

没想到几天后一个做硬件的同学给了我块开发板。

同学说:我这里有CCS,但是实验室的正版软件,没法装到其它机器上。你可能没法玩。

我:没事,上学期上嵌入式的课老师给拷过CCS……

同学:!!!!那给你玩吧……

于是在回来在Ti的wiki上被科普了一把,想要使用msp430单片机可以用TI提供的两种IDE,iar和ccs。

ccs提供免费版本,限制16k程序,使用需要遵循美国政府blabla进出口管理条例法律,特别麻烦,不过注册申请后两小时就批准了。

win下的同学还可以去使用iar,同样免费版本限制十六kb程序,我特马第一个程序还不到200字节。我之所以下载ccs,因为ccs有linux版本

但是……我装不上……原因就不说了,各种依赖问题,我本来也不倾向使用IDE。

还有一套开源的东西可以用来开发,gcc/gdb/一堆binutils和c库+mspdebug,自由无限制,不需要注册,没有程序大小限制,开放可信赖,还是熟悉的工具集。

在gentoo上设置开发环境

Generating a cross-compiler by hand is a long and painful process. This is why it has been fully integrated into Gentoo!

gentoo下的交叉编译似乎特别容易= =,因为crossdev的存在。

不要问我怎么设置:看这里 cross-compiler

我之前似乎在linux下写win32程序时把东西都搞好了……不记得当时做了什么,大概就是

emerge crossdev

紧接着就可以生成msp430平台的系列工具了,我们要指定target、需要gdb等等……

sudo crossdev -S –ov-output /usr/portage/ –ex-gdb -t msp430

经过不那么漫长的等待,你会发现msp430一整套toolchain都已经搭好了。

让我们写个程序吧,LED闪灯小程序 main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <msp430g2553.h>

int main(int argc, const char *argv[])
{

volatile int i;

/* Stop watchdog timer */
WDTCTL = WDTPW | WDTHOLD;

/* Setup bit 0 of P1 and bit 6 of P1 as output */
P1DIR = 0x41;

/* Setup bit 0 of P1 to 0 and bit 6 of P1 to 1*/
P1OUT = 0x40;

/* Loop forever */
while (1){
/* Toggle bit 0,6 of P1 */
P1OUT ^= 0x41;
/* Just delay */
for (i = 0; i < 0x9000; i++){}
}
}

其实我都是抱着试试看的心理一边改别人的程序一边试的,单片机上确实写的是

MSP430G2553

然后编译,编译时要指定芯片,不要问我为什么,msp430-gcc就是这个德性

msp430-gcc -mmcu=msp430g2553 -g main.c -o main.elf

最后写进单片机吧。其实板子预先内置的就是这个程序。你可以把它改成只闪一个灯的。

我们要先安装mspdebug。

MSPDebug is a free debugger for use with MSP430 MCUs

sudo emerge --autounmask-write mspdebug
sudo dispatch-conf
sudo emerge mspdebug

然后指定驱动,至于这个驱动是调试接口的驱动,详情参考这里

sudo mspdebug rf2500

接触读写硬件的权限是必要的。

  ~/Work/msp430 $ sudo mspdebug rf2500                              
MSPDebug version 0.22 - debugging tool for MSP430 MCUs
Copyright (C) 2009-2013 Daniel Beer <[email protected]>
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Trying to open interface 1 on 007
rf2500: warning: can't detach kernel driver: No such file or directory
Initializing FET...
FET protocol version is 30394216
Set Vcc: 3000 mV
Configured for Spy-Bi-Wire
fet: FET returned error code 4 (Could not find device or device not supported)
fet: command C_IDENT1 failed
Using Olimex identification procedure
Device ID: 0x2553
   Code start address: 0xc000
   Code size         : 16384 byte = 16 kb
   RAM  start address: 0x200
   RAM  end   address: 0x3ff
   RAM  size         : 512 byte = 0 kb
Device: MSP430G2xx3
Number of breakpoints: 2
fet: FET returned NAK
warning: device does not support power profiling
Chip ID data: 25 53

Available commands:
     =           erase       isearch     power       save_raw    simio        
     alias       exit        load        prog        set         step        
     break       fill        load_raw    read        setbreak    sym          
     cgraph      gdb         md          regs        setwatch    verify      
     delbreak    help        mw          reset       setwatch_r  verify_raw  
     dis         hexout      opt         run         setwatch_w  

Available options:
     color                       gdb_loop                    
     enable_bsl_access           gdbc_xfer_size              
     enable_locked_flash_access  iradix                      
     fet_block_size              quiet                        
     gdb_default_port            

Type "help <topic>" for more information.
Use the "opt" command ("help opt") to set options.
Press Ctrl+D to quit.

(mspdebug)  

接着输入

prog main.elf

就把程序烧进……不知道什么东西去了。当年嵌入式的课白听了,就记的几个名词……

(mspdebug) prog main.elf
Erasing...
Programming...
Writing  148 bytes at c000 [section: .text]...
Writing   32 bytes at ffe0 [section: .vectors]...
Done, 180 bytes total

接着run就可以看灯轮流闪了

(mspdebug) run
Running. Press Ctrl+C to interrupt...

如果要调试,直接输入gdb就可以,

(mspdebug) gdb
Bound to port 2000. Now waiting for connection...

在另一个终端:

  ~/Work/msp430 ? msp430-gdb -q
(gdb) target remote localhost:2000
Remote debugging using localhost:2000
0x0000c076 in ?? ()
(gdb) file main.elf
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from /home/lyy/Work/msp430/main.elf...done.
(gdb) n

接着还能用makefile简化这些过程,但,我不会makefile……

last but not least

这套工具链可以在其它linux如debian上很容易的搭建起来,就几个apt-get的事,虽然还没在debian下试过,但debian质量,值得信赖。

在windows下也可以使用这一整套工具,相比ccs来说具有……好处开头说了,支持也不错。

参考文献,不一一标注引用,还有好多忘了:

  • http://coldnew.github.io/blog/2013/11/18_686_g.html
  • http://processors.wiki.ti.com/index.php/Download_CCS
  • http://www.ti.com.cn/cn/lit/ug/zhcu010c/zhcu010c.pdf
  • http://home.eeworld.com.cn/my/space-uid-139222-blogid-72202.html
  • http://blog.sina.com.cn/s/blog_a47d75c60101axsp.html
  • http://develissimo.com/forum/topic/115418/
  • http://processors.wiki.ti.com/index.php/Blink_your_first_LED
  • http://43oh.com/2010/08/10-beginner-msp430-tutorials-and-counting/

哈,第一次玩硬件……向赞助我片子的同学汇报时同学说你怎么进展这么快!!!!

只来得及玩了一天就陷入加班写文档的狂潮之中去了……摔!!!

最后附上个呼吸灯程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//Original code is here, //http://osx-launchpad.blogspot.com/2010/11/breathing-led-effect-with-launchpad.html
//This is slight modification to work with Ti CCS devtool


#include <msp430.h>

int idx = 0; // Index to PWM's duty cycle table (= brightness)

const unsigned char curve[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 2, 2, 2, 2, 2,
2, 2, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7,
8, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 11, 12, 12, 13,
13, 13, 14, 14, 15, 15, 15, 16,
16, 17, 17, 18, 18, 18, 19, 19,
20, 20, 21, 21, 22, 22, 23, 23,
24, 24, 25, 25, 26, 26, 27, 27,
28, 29, 29, 30, 30, 31, 31, 32,
33, 33, 34, 34, 35, 36, 36, 37,
38, 38, 39, 39, 40, 41, 41, 42,
43, 43, 44, 45, 46, 46, 47, 48,
48, 49, 50, 50, 51, 52, 53, 53,
54, 55, 56, 56, 57, 58, 59, 59,
60, 61, 62, 62, 63, 64, 65, 66,
66, 67, 68, 69, 70, 70, 71, 72,
73, 74, 75, 75, 76, 77, 78, 79,
80, 80, 81, 82, 83, 84, 85, 86,
87, 87, 88, 89, 90, 91, 92, 93,
94, 95, 95, 96, 97, 98, 99, 100,
101, 102, 103, 104, 105, 106, 106, 107,
108, 109, 110, 111, 112, 113, 114, 115,
116, 117, 118, 119, 120, 121, 122, 122,
123, 124, 125, 126, 127, 128, 129, 130,
131, 132, 133, 134, 135, 136, 137, 138,
139, 140, 141, 142, 143, 144, 145, 146,
147, 148, 149, 150, 151, 152, 153, 154,
155, 156
};

int main(void)
{

// Stop watchdog
WDTCTL = WDTPW + WDTHOLD;

// Set clock to 1 MHz
DCOCTL= 0;
BCSCTL1= CALBC1_1MHZ;
DCOCTL= CALDCO_1MHZ;

// SMCLK = 1 MHz / 8 = 125 KHz (SLAU144E p.5-15)
BCSCTL2 |= DIVS_3;

// Make P1.6 (green led) an output. SLAU144E p.8-3
P1DIR |= BIT6;

// P1.6 = TA0.1 (timer A's output). SLAS694C p.41
P1SEL |= BIT6;

// PWM period = 125 KHz / 625 = 200 Hz
TACCR0 = 625;

// Source Timer A from SMCLK (TASSEL_2), up mode (MC_1).
// Up mode counts up to TACCR0. SLAU144E p.12-20
TACTL = TASSEL_2 | MC_1;

// OUTMOD_7 = Reset/set output when the timer counts to TACCR1/TACCR0
// CCIE = Interrupt when timer counts to TACCR1
TACCTL1 = OUTMOD_7 | CCIE;

// Initial CCR1 (= brightness)
TACCR1 = 0;

// LPM0 (shut down the CPU) with interrupts enabled
__bis_SR_register(CPUOFF | GIE);

}

// This will be called when timer counts to TACCR1.
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A(void)
{

int new_ccr1 = 1;

// Clear interrupt flag
TACCTL1 &= ~CCIFG;

if (idx < 500) {
new_ccr1 = curve[idx++ >> 1];
} else if (idx < 1000) {
new_ccr1 = curve[(999 - idx++) >> 1];
} else {
idx = 0;
}
// Wait to set the new TACCR1 until TAR has gone past it, so that we
// don't get interrupted again in this period.
while (TAR <= new_ccr1);
TACCR1 = new_ccr1;
}