LPC2132 調(diào)試記
1、查看快速入門,快速掌握燒寫FLASH和JTAG工具,ADS1.2。(相關(guān)工具在Software&Driver文件夾下)
(1)LPC2131 FLASH工具:philips公司的LPC2100 Flash Utility V2.2.0 .
(a)波特率設(shè)置為9600,時(shí)鐘設(shè)為11050KHZ,time-ou[sec]:2(另外,buffer->flashbuf operation->Download flash可以從flash上下載程序到本機(jī)后,再與本機(jī)的程序比較是否一致,選擇Compare Flash時(shí)可以進(jìn)行flash上程序的校驗(yàn))
(b)"Upload to Flash"前先要P0.14對地拉低(將ISP(JP1)跳線),程序固化后,將ISP(JP1)跳線帽斷開,重新復(fù)位系統(tǒng)即可運(yùn)行程序。LPC2100系列ARM7微控制器芯片具有ISP功能,可以通過串口進(jìn)行程序下載。(這點(diǎn)非常重要,在我們公司的硬件出板后,我調(diào)試板子時(shí),用JTAG調(diào)試,程序可以運(yùn)行,但是用串口下載完程序,重新復(fù)位后沒有一點(diǎn)反應(yīng)。后來查過就是硬件設(shè)計(jì)上沒有設(shè)置這個(gè)跳線。也沒有按照如上的要求來進(jìn)行程序的下載和運(yùn)行。下載和運(yùn)行時(shí)P0.14腳都為低電平。說明一直是在ISP模式下。)
(2)EasyJTAG-H和H-JTAG可進(jìn)行硬件仿真調(diào)試(不知道有誰知道如何固化,敬請賜教)EasyJtag可以固化,但是我使用時(shí),總是有錯誤出現(xiàn),連接不到,網(wǎng)上查過錯誤原因,很多人有過這樣的錯誤,但是沒有找到解決方法。
(3)ADS1.2集成開發(fā)環(huán)境幾個(gè)注意點(diǎn):
(a)Debug Settings ->linker->ARM Linker設(shè)置RO(或者指定.scf文件)
(b)Debug Settings ->Target->Target Settings->Post-Linker (ARM fromELF)
(c)Debug Settings ->Liker->ARM fromELF指定output format(Intel 32 bit Hex)
和output file name(/xx/xx/xxx.hex)
(d)指定生成的文件夾為DebugInRam,如果是RelInFlash的話,會對芯片加密,需
要用ISP全局擦除后,才能恢復(fù)JTAG調(diào)試及ISP讀/寫操作。
(e) ADX配置好調(diào)試目標(biāo)。Option->configure Target->ADD->D:Program
FilesH-JTAG V0.3.1目錄下的H-JTAG .dll,點(diǎn)擊“打開”即可。
Option->configure Target ->Choose Target->H-JTAG
2、快速運(yùn)行示例代碼。在此基礎(chǔ)上進(jìn)行修改可以省去很多時(shí)間。移植了UCOS-II操作系統(tǒng),修改了I2C(模擬I2C),UART0, BEEP(用于測試),中斷處理,用一個(gè)硬件時(shí)鐘模擬多個(gè)軟件時(shí)鐘。參考網(wǎng)上代碼后修改(作者:21icbbs LPC900,2005-08)示例代碼見最后例1。
3、開發(fā)板上調(diào)試完畢后,關(guān)鍵在于板子出來后的調(diào)試。此時(shí)的問題,可能是硬件,可能是軟件。需要軟硬件配合調(diào)試。做好工作日志,因?yàn)榇藭r(shí)的問題如果不做好記錄,會導(dǎo)致大貨時(shí)問題沒有得到更改。比如前面提到的這次硬件設(shè)計(jì)上沒有設(shè)計(jì)ISP跳線的問題。另外,開發(fā)板上的某些硬件可能與實(shí)際板子的有所不同,要稍加注意。如:我們公司出板時(shí)用的CPU是LPC2132,與LPC2131的不同是LPC2132是64K+16K,還有時(shí)鐘更改了,不要忘記在代碼中把時(shí)鐘的值更改過來。其他的基本上沒有什么問題,直接移植就可以了?,F(xiàn)在還差的就是做個(gè)最小文件系統(tǒng)啦(留出一塊空間512字節(jié),可存儲,可擦除,還要帶CRC校驗(yàn))啊,努力吧。要學(xué)的東西太多啦。
4、附帶講一下減少代碼的一些辦法。
(a)在startup.s中的跳轉(zhuǎn)函數(shù)入口,不要寫main函數(shù),改為其它名字,也就是把自己的入口函數(shù)的名字改掉。因?yàn)槿绻莔ain入口的話,ads1.2會做一大堆全局變量的COPY和搬移。在用ADS單步調(diào)試時(shí)會發(fā)現(xiàn)在進(jìn)入main之前會先做_main.這就是在做這些工作。但是如果這樣做的話,要記得全局變量和靜態(tài)變量RODATA段的初始值會丟失,需要在用這些變量前再賦下值。
(b)盡量不用或少用庫函數(shù),如atoi,strcmp,strcp等等,而是由自己去實(shí)現(xiàn),這樣可以減少鏈接一些不必要的庫文件。
以上二者做的適中的話,可能可以減少10K的代碼量
(c)UCOS_II.h中提供了內(nèi)核裁減的可配置,輕松減少代碼。
例1:target.c文件
//定義軟件定時(shí)器數(shù)量(至少1個(gè))
#define TIMER_N8
//定義軟件定時(shí)器結(jié)構(gòu)
//每個(gè)定時(shí)器只占用2個(gè)字節(jié)
struct
{
volatile unsigned TV:32;//32位定時(shí)值
unsigned long da
void (*function)(unsigned long);//callback
volatile unsigned TR:1;//起停標(biāo)志,0-停止運(yùn)行,1-開始運(yùn)行
volatile unsigned TF:1;//溢出標(biāo)志,0-未溢出,1-溢出
}Timer[TIMER_N];
/*
利用定時(shí)器T0模擬多個(gè)軟件定時(shí)器
原創(chuàng)作者:21icbbs LPC900,2005-08
更改:May Wong 2008-6-13 (LPC2131)
特點(diǎn):
只占用一個(gè)硬件定時(shí)器T0,就可以擴(kuò)展出多達(dá)數(shù)十個(gè)以上的軟件定時(shí)器
軟件定時(shí)器基本定時(shí)單位是5ms,定時(shí)范圍很寬:0.01~163.84s
軟件定時(shí)器數(shù)量可以按需要設(shè)定,
利用定時(shí)器T0的自動重裝特性,能夠?qū)崿F(xiàn)所有軟件定時(shí)器的精確定時(shí)
所有軟件定時(shí)器都工作在32位倒計(jì)時(shí)方式,用TR和TF位控制,使用極為方便
第0號定時(shí)器專門用于Delay()函數(shù),其它定時(shí)器可供用戶程序自由使用
*/
/*
函數(shù):TimerOn()
功能:啟動定時(shí)器
參數(shù):
t:定時(shí)器初值,取值0~4294967295
t>0時(shí),定時(shí)(0.01*t)s
t=0時(shí),定時(shí)163.84s
unsigned long da
void (*function)(unsigned long): callback function
return:-1(error)else定時(shí)器序號
*/
int TimerOn(unsigned int t,unsigned long funpara,void(*function)(unsigned long))
{
unsigned int i;
INT32U da_year,da_mon,da_day,ti_hour,ti_min,ti_sec;/*test start time*/
for (i = 1; i < TIMER_N;i++)
{
if (Timer[i].TR == 0)
{
//Timer[i].TR = 0;
Timer[i].TF = 0;
Timer[i].TV = t;
Timer[i].TR = 1;
Timer[i].function = function;
Timer[i].da
break;
}
}
if (i == TIMER_N)
return -1;
else
returni;
}
/*
函數(shù):TimerOff()
功能:關(guān)閉定時(shí)器
參數(shù):
n:定時(shí)器序號
*/
void TimerOff(unsigned char n)
{
Timer[n].TR = 0;
Timer[n].TF = 0;
}
/*
函數(shù):Delay()
功能:延時(shí)0.01~163.84s
參數(shù):
t:延時(shí)參數(shù),取值0~16383
t>0時(shí),延時(shí)(0.01*t)s
t=0時(shí),延時(shí)163.84s
*/
void Delay(unsigned int t)
{
Timer[0].TR = 0;
Timer[0].TF = 0;
Timer[0].TV = t;
Timer[0].TR = 1;
// TimerOn(t,NULL,NULL);
for (;;)
{
//PCON |= 0x01;
T0TCR |= 0x01;/*reset*/
if (Timer[0].TF)
{
TimerOff(0);
break;
}
}
}
/*********************************************************************************************************
** Function name:Timer0_Exception
**
** Descriptions:Timer0 interrupt service function
**
** input parameters:None
** Returned value:None
**
** Used global variables:None
** Calling modules:None
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
/*
函數(shù):Timer0_Exception()
功能:定時(shí)器中斷服務(wù)函數(shù),每(Fcclk / 4) * 1/ 200中斷1次
*/
void Timer0_Exception(void)
{
//unsigned char i;
unsigned int i;
//TF2 = 0;
for ( i=0; i { //beep();//beep ok if (Timer[i].TR) { if ( --Timer[i].TV == 0 ) { UART0Putch(0); Timer[i].TF = 1; TimerOff(i); (Timer[i].function)(Timer[i].da UART0Putch(0); //beep(); //UART0Putch(0); } } } T0IR = 0x01;/* match tunnel 1 intrrupt flag清除中斷標(biāo)*/ VICVectAddr = 0;//interrupt close通知中斷控制器中斷結(jié)束 OSTimeTick(); } /********************************************************************************************************* ** Function name:Timer0Init ** ** Descriptions:Initialize the Time0 ** ** input parameters:None ** Returned value:None ** ** Used global variables:None ** Calling modules:None **------------------------------------------------------------------------------------------------------- ** Modified by: ** Modified date: **------------------------------------------------------------------------------------------------------ ********************************************************************************************************/ void Timer0Init(void) { unsigned int x; unsigned char i; for ( i=0; i { Timer[i].TR = 0; Timer[i].TF = 0; Timer[i].TV = 0; } T0IR = 0xffffffff;/*timer intrrupt register1 reset*/ T0PR= 0;/*時(shí)鐘不分頻*/ T0TC = 0;/*counter*/ T0TCR = 0x01;/*counter control reginster 1 reset */ T0MCR = 0x03;/*[0:1] 11tc reset/ intrrupt when match*/ T0MR0 = (Fpclk / OS_TICKS_PER_SEC);/*(Fcclk / 4) * 1/ 2005ms鐘定時(shí)*/ } /********************************************************************************************************* ** Function name:VICInit ** ** Descriptions:Initialize the Interrupt Vevtor Controller ** ** input parameters:None ** Returned value:None ** ** Used global variables:None ** Calling modules:None ** **------------------------------------------------------------------------------------------------------ ********************************************************************************************************/ void VICInit(void) { extern void IRQ_Handler(void); extern void Timer0_Handler(void); extern void I2c_Handler(void); #if 0 extern void UART0_Handler(void); #endif VICIntEnClr = 0xffffffff;/*clear interrupt*/ VICDefVectAddr = (uint32)IRQ_Handler; VICVectAddr0 = (uint32)Timer0_Handler;/*設(shè)置中斷服務(wù)程序地址*/ VICVectCntl0 = (0x20 | 0x04);/*設(shè)置定時(shí)器0中斷通道分配最高優(yōu)先級*/ VICIntEnable = 1 << 4;/*使能定時(shí)器0中斷 /*I2c*/ VICVectAddr12 = (uint32)I2c_Handler; VICVectCntl12 = (0x20 | 9); #if 0 /*Uart*/ VICVectAddr14 = (uint32)UART0_Handler; VICVectCntl14 = (0x20 | 0x06); VICIntEnable = 1 << 6; #endif } /********************************************************************************************************* ** Function name:TargetInit ** ** Descriptions:Initialize the target board; it is called in a necessary place, change it as **needed ** ** input parameters:None ** Returned value:None ** ** Used global variables:None ** Calling modules:None ** ********************************************************************************************************/ void TargetInit(void) { OS_ENTER_CRITICAL(); srand((uint32) TargetInit); VICInit(); Timer0Init(); I2cInit(100000); UART0Init(115200); OS_EXIT_CRITICAL(); } Main中測試代碼如下: #include "config.h" #defineTASK_STK_SIZE64 #defineLEN50 //OS_STKTaskStk[TASK_STK_SIZE]; OS_STKTaskStartStk[TASK_STK_SIZE]; voidTaskStart(void *da #defineBEEP(1<<7)/* P0.7引腳控制BEEPjust test I2C */ void initbeep() { /*關(guān)閉BEEP */ IO0DIR |= BEEP;/*設(shè)置BEEP控制口為輸出*/ PINSEL0 = (PINSEL0 & 0xffff3fff); IO0SET = BEEP; } void beep() { /*for test*/ IO0CLR = BEEP; OSTimeDly(OS_TICKS_PER_SEC / 2);/*蜂鳴器響一聲*/ IO0SET = BEEP; } /********************************************************************************************************* **函數(shù)名稱: main **功能描述: c語言的主函數(shù),由它啟動多任務(wù)環(huán)境 **輸 入:無 **輸 出:無 **全局變量:無 **調(diào)用模塊: PC_DispClrScr,OSInit,OSTaskCreate,OSStart **------------------------------------------------------------------------------------------------------ ********************************************************************************************************/ int main (void) { OSInit(); TargetInit(); initbeep(); OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 5); OSStart(); return 0; } void testfun3(unsigned long para) { UART0Putch(3); } void testTimer() { /* -1 not enough timer else return timer No.*/ if(TimerOn(800,10,testfun3) == -1) beep(); else UART0Putch(n);//ok } /********************************************************************************************************* **函數(shù)名稱: TaskStart **功能描述:μCOS-II的第一個(gè)任務(wù),通常由它初始化目標(biāo)板和建立其它任務(wù) **輸 入:無 **輸 出:無 **全局變量:無 **調(diào)用模塊: ** ********************************************************************************************************/ voidTaskStart (void *pdata) { pdata = pdata;/*避免編譯警告*/ /*test timer0*/ testTimer(); while(1) } /*********************************************************************************************************End Of File***************************
評論