介紹
DS80C400包含一個提供網(wǎng)絡(luò)棧、內(nèi)存管理和進程調(diào)度的ROM,可以靈活地用于由Java、C和8051匯編編程的應(yīng)用中。SDCC為8051器件提供了一個免費、開放源碼的編譯器,并兼容DS80C400的24位尋址模式。用C編寫的復(fù)雜應(yīng)用程序在Dallas Semiconductor提供的庫的幫助下,可以很容易地使用DS80C400 ROM功能創(chuàng)建。
本應(yīng)用筆記闡述了如何使用SDCC工具來創(chuàng)建DS80C400應(yīng)用程序。從一個HelloWorld應(yīng)用程序開始,然后說明如何使用ROM庫來實現(xiàn)一個簡單的HTTP服務(wù)器。這里的應(yīng)用程序是針對TINIm400參考模塊編寫和創(chuàng)建的,用于具有其它存儲器配置的設(shè)計時必須進行相應(yīng)修改。
從SDCC編譯器開始
遵循以下步驟,使用SDCC編譯器來完成您的第一個DS80C400的C應(yīng)用程序:
-
安裝SDCC編譯器1
- 從SDCC網(wǎng)站上下載最新版本SDCC編譯器的安裝文件。
- 遵循安裝文件的指示(可能是sdcc/doc/INSTALL.txt)。
-
使用你喜歡的文本編輯器創(chuàng)建一個新文件"main.c"。在文件中寫入以下代碼:
#include < stdio.h > void main () { printf("Hello Universe!!!!....Welcome to SDCC Tini Test Program"); while (1) { } }
一定要保存文件內(nèi)容。
-
從SDCC C庫站點2中拷貝文件startup400.a51和reg400.inc (包含在啟動代碼下載中),并保存到您保存main.c文件的目錄中。此文件包含startup_code函數(shù),將在應(yīng)用程序啟動時調(diào)用該函數(shù),從而對DS80C400芯片進行初始化。啟動代碼完成以下工作:
- 將DS80C400配置成24位連續(xù)地址模式
- 配置定時器2用來為串口產(chǎn)生115200的波特率
- 初始化數(shù)據(jù)存儲器
-
從SDCC C庫站點拷貝ROM initialization庫文件(從init庫文件下載的rominit.lib和rom400.h),并將其解壓縮至相同目錄下。庫文件是壓縮的,使用WinZip或gunzip/tar解壓縮包。
-
在編譯我們的"Hello Universe"應(yīng)用程序之前,我們需要在一個SDCC安裝的支持文件中作一個小改動,覆蓋缺省的DS80C400支持函數(shù)并使用Dallas Semiconductor的C庫代替。進行以下改動:
- 將\\SDCC\\lib\\ds400\\libds400.lib文件重命名為\\SDCC\\lib\\ds400\\libds400.lib.old
- 建立一個名為\\SDCC\\lib\\ds400\\libds400.lib的空文件(使用touch命令或在您喜歡的文本編輯器中建立一個新文件)
-
構(gòu)建"Hello Universe"應(yīng)用程序...
-
要由我們的startup400.a51文件創(chuàng)建一個目標(biāo)文件(.rel),在命令行執(zhí)行以下命令:
asx8051 -losffgp startup400.a51
asx8051是SDCC工具提供的匯編器。匯編器提供的參數(shù)選項有:| Option | Purpose |
| -------- | ----------------------------------------------------- |
| l | generates a list file |
| o | generates an object file |
| s | generates a symbol file |
| ff | flag reolcatable references by mode in listing file |
| g | make undefined symbols be global |
| p | disables listing pagination |
"los"參數(shù)是必須的,因為連接器需要列表、目標(biāo)和符號文件來生成可執(zhí)行文件。"ff"和"p"參數(shù)生成一個可讀的列表文件。"g"參數(shù)通知匯編器在發(fā)現(xiàn)一個沒有定義的符號且該符號未聲明為外部變量時不報錯。
-
為了由main.c生成一個目標(biāo)文件,執(zhí)行以下命令:
sdcc -c -mds400 --model-flat24 --stack-10bit --no-xinit-opt main.c
sdcc為編譯器。
傳遞給編譯器的參數(shù)選項為:
Option Purpose -c compiles main.c and creates an object file -mds400 generates code for the DS80C400 processor --model-flat24 use the 24-bit contiguous memory model --stack-10bit use the 1024-byte extended stack (10 bit stack addresses) --no-xinit-opt don't initialize the external RAM memory area p disables listing pagination 注意列表中最后三個參數(shù)是雙破折號。
-
為了連接目標(biāo)文件并構(gòu)建可執(zhí)行文件,執(zhí)行以下命令:
sdcc -mds400 --model-flat24 --stack-10bit -Wl-r --xram-loc 0x10000 --xram-size 0x3fff --code-loc 0x400000 main.rel startup400.rel -l rominit.lib
這里使用的新參數(shù)為:| Option | Purpose |
| ------------- | -------------------------------------------------------------- |
| -WI | pass options through to the linker |
| --xram-loc | external RAM start address (only RAM for SDCC variable use!) |
| --xram-size | external RAM size (only RAM for SDCC variable use!) |
| --code-loc | code starting address |
| -l | include the specified libraries |
| p | disables listing pagination |
請注意xram-loc、 xram-size和code-loc參數(shù)為雙破折號。也要注意給命令指定的RAM將會用來存儲SDCC變量,不應(yīng)該和init_rom函數(shù)中用來初始化DS80C400所使用的存儲器范圍沖突―此存儲器用作網(wǎng)絡(luò)棧和存儲器管理。
-
為了壓縮可執(zhí)行文件并生成一個十六進制文件,執(zhí)行以下命令:
packihx main.ihx>hellouniverse.hex
packihx命令通過將連續(xù)數(shù)據(jù)記錄累積至16個字節(jié)來壓縮可執(zhí)行文件。
-
有了一個可執(zhí)行文件后,我們需要將應(yīng)用程序下載到TINIm400模塊中并運行它。### 將示例應(yīng)用程序加載到TINIm400模塊
本節(jié)說明如何使用Maxim/Dallas Semiconductor提供的 微控制器工具包(MTK) 向TINIm400驗證模塊中加載由SDCC編譯器生成的十六進制文件。目前可用的MTK版本只支持Windows?。
如果您的開發(fā)環(huán)境不是Windows,需要使用JavaKit應(yīng)用程序來下載和執(zhí)行應(yīng)用程序。要使用JavaKit,您必須有Java運行環(huán)境3 (版本至少為1.2)并且安裝Java Communications API ^4^ 。JavaKit工具包含在TINI軟件開發(fā)包中。寫本文的時候,發(fā)布的最新固件是固件版本1.13。運行JavaKit的指導(dǎo)說明可以在TINI SDK docs目錄下的Running_JavaKit.txt文件中找到。如果您在運行MTK或JavaKit時遇到技術(shù)問題,可能其他人已經(jīng)遇到過類似問題并且已經(jīng)發(fā)表在Dallas Semiconductor的討論區(qū)中。
最新版本的MTK應(yīng)用軟件可下載。要安裝MTK,請運行安裝文件并遵照提示操作。成功安裝后,會增加一個新的菜單項: Start->All Programs->Dallas Semiconductor MTK。 MTK啟動后,會出現(xiàn)圖1所示的對話框。
圖1. 啟動時MTK選項
選擇選項TINI,以操作TINIm400評估板。
選擇了TINI之后,會打開MTK主窗口。從Options->Configure Serial Port菜單選項中選擇您將用來和TINIm400通訊的串口。然后,選擇Tini->Tini Options菜單項,就會出現(xiàn)下面的對話框。選擇DSTINIm400按鈕,配置MTK用于和TINIm400板通訊。圖2顯示了帶有DSTINIm400按鈕的對話框。
圖2. 選擇TINIm400配置選項
選擇Tini->Open COMx at xxx baud菜單選項打開串口。接著選擇Tini->Reset選項復(fù)位評估板。會出現(xiàn)DS80C400的加載提示:
DS80C400 Silicon Software - Copyright (C) 2002 Maxim Integrated
Detailed product information available at http://www.maximintegrated.com
Welcome to the TINI DS80C400 Auto Boot Loader 1.0.1
>
從文件菜單中選擇Load HEX File。找到我們剛剛生成的hellouniverse.hex文件并選中。一旦您的程序加載后有兩種方法運行它。因為我們將程序加載到40區(qū),您可以輸入:
> B40
> X
要選擇40區(qū)并運行那里的代碼。您也可以輸入:
> E
這會使ROM查找可執(zhí)行的代碼。它查找一個標(biāo)識當(dāng)前區(qū)具有可執(zhí)行代碼的特定標(biāo)簽。此標(biāo)簽由文本'TINI'組成,其后面緊跟著當(dāng)前區(qū)的號碼(或零),并位于當(dāng)前區(qū)的0002h地址。SDCC編譯器在生成的匯編代碼中插入此標(biāo)簽。如果打開為hellouniverse工程生成的main.asm源代碼,您會找到下面的代碼段:
.area CSEG (CODE)
interrupt_vect:
; DS80C400 IVT must be generated at runtime.
sjmp __sdcc_400boot
.ascii 'TINI' ; required signature for 400 boot loader.
.db 0 ; selected bank or zero...
__sdcc_400boot:
ljmp __sdcc_gsinit_startup
注意sjmp__sdcc_400boot語句位于40區(qū)的0000h地址。其后跟隨可執(zhí)行標(biāo)簽{ 'T', 'I', 'N', 'I', 0h},由于simp語句為兩個字節(jié),因此該標(biāo)簽位于地址0002處。當(dāng)您鍵入'E'時,ROM從C0h區(qū)開始向下搜索可執(zhí)行代碼。如果您鍵入'E'時,執(zhí)行了其它的代碼,則意味著ROM在一個比您的代碼加載位置400000h更高的地址找到了一個可執(zhí)行標(biāo)簽。您可能需要找到此標(biāo)簽的位置,并刪除那個區(qū)的內(nèi)容。### 和ROM以及SDCC ROM庫接口
在高速微控制器用戶指南DS80C400補充資料中說明了在匯編語言中調(diào)用ROM函數(shù)的過程。但是,在C中調(diào)用這些ROM函數(shù)會復(fù)雜一些。必須將參數(shù)從SDCC C編譯器的規(guī)則轉(zhuǎn)換成ROM使用的規(guī)則。SDCC編譯器通過硬件堆棧、累加器和數(shù)據(jù)指針相結(jié)合的方式來傳遞參數(shù)。ROM函數(shù)采用許多不同的方式來接受參數(shù)。例如,socket函數(shù)接收存儲在一個外部RAM緩沖區(qū)中的參數(shù)。相反地,許多功能函數(shù)接收由特殊功能寄存器或直接存儲器位置傳遞的參數(shù)。為了從SDCC調(diào)用方式轉(zhuǎn)換成ROM參數(shù)方式,Dallas Semiconductor已經(jīng)編寫了訪問ROM函數(shù)的庫。
在您的C程序中使用ROM函數(shù)只需包含一個頭文件并與相應(yīng)的庫文件連接即可。用于SDCC編譯器的ROM庫包括:
- ROM初始化程序
- DHCP客戶端
- 進程調(diào)度
- Sockets (TCP、UDP和Multicast)
- TFTP客戶端
- 功能函數(shù)(CRC16, 隨機數(shù))
在寫本文時,還沒有為SDCC編譯器提供包括如文件系統(tǒng)、郵件客戶端和HTTP服務(wù)器之類的擴展庫。請關(guān)注SDCC庫主頁上的DS80C400升級信息,我們會添加支持SDCC的庫。### 簡單應(yīng)用:HTTP服務(wù)器
編寫了一個簡單的http服務(wù)器來說明如何使用一些ROM庫函數(shù),特別是socket和進程調(diào)度庫。這個示例會偶爾通過網(wǎng)絡(luò)時間服務(wù)器更新它的時間,并且通過它的web服務(wù)器提供這個信息。
示例應(yīng)用程序由兩個模塊組成,一個HTTP服務(wù)器和SNTP客戶端。主程序生成一個新的子任務(wù)來運行http服務(wù)器,用于處理80端口上的客戶連接。父任務(wù)每60秒會試圖通過時間服務(wù)器同步當(dāng)前時間。
SNTP客戶端模塊
以下代碼段實現(xiàn)SNTP客戶端模塊的核心功能。
socket_handle = socket(0, SOCKET_TYPE_DATAGRAM, 0);
// set a timeout of about 2 seconds
for (i=0;i< 256;i++)
buffer[i] = 0;
buffer[0] = 0x0;
buffer[1] = 0x0;
buffer[2] = 0x8;
buffer[3] = 0x0;
setsockopt(socket_handle, 0, SO_TIMEOUT, buffer, 200);
buffer[2] = 0; //reset since we used this in call to setsockopt
buffer[0] = 0x23; // No warning/NTP Ver 4/Client
address.sin_addr[12] = TIME_NIST_GOV_IP_MSB;
address.sin_addr[13] = TIME_NIST_GOV_IP_2;
address.sin_addr[14] = TIME_NIST_GOV_IP_3;
address.sin_addr[15] = TIME_NIST_GOV_IP_LSB;
address.sin_port_high = (NTP_PORT/0x100); //higher byte of port number
address.sin_port_low = (NTP_PORT%0x100); //lower byte of port number
sendto(socket_handle, buffer, 48, 0, &address, sizeof(struct sockaddr));
recvfrom(socket_handle, buffer, 256, 0, &address, sizeof(struct sockaddr));
//SDCC uses little Endian for storing data, so reorganize the data before converting it to long
buffer[0]=buffer[43];
buffer[1]=buffer[42];
buffer[2]=buffer[41];
buffer[3]=buffer[40];
timeStamp = *(unsigned long *)(&buffer[0]);
formatTimeString(timestamp - (5 * SECONDS_PER_HOUR), "Tampa, USA",
last_time_reading_1);
formatTimeString(timeStamp - (3 * SECONDS_PER_HOUR), "Sao Paulo, Brazil",
last_time_reading_2);
formatTimeString(timeStamp + (1 * SECONDS_PER_HOUR),"Marseille, France",
last_time_reading_3);
formatTimeString(timeStamp + (5 * SECONDS_PER_HOUR) + (30 *
SECONDS_PER_MINUTE), "Bangalore, India",
last_time_reading_4);
formatTimeString(timeStamp + (8 * SECONDS_PER_HOUR), "Hsinchu, Taiwan",
last_time_reading_5);
last_reading_seconds = getTimeSeconds();
closesocket(socket_handle);