這個(gè)時(shí)間服務(wù)器應(yīng)用程序的另一個(gè)子模塊為web服務(wù)器。此應(yīng)用程序中的HTTP服務(wù)器實(shí)現(xiàn)了一個(gè)RFC 2068中描述的HTTP服務(wù)器簡(jiǎn)易版本。在我們的版本中,僅支持GET方法,忽略輸入頭文件,并且?guī)缀醪唤o出輸出包頭。在撰寫(xiě)這篇應(yīng)用筆記時(shí)尚未提供文件系統(tǒng)庫(kù),因此示例應(yīng)用程序動(dòng)態(tài)地生成HTML網(wǎng)頁(yè)。
通過(guò)調(diào)用Berkley-style socket函數(shù)來(lái)創(chuàng)建服務(wù)器socket。這使得建立一個(gè)服務(wù)器socket十分容易。以下代碼給出我們的簡(jiǎn)易HTTP服務(wù)器的創(chuàng)建、綁定和接受新連接。
struct sockaddr local;
unsigned int socket_handle, new_socket_handle, temp;
socket_handle = socket(0, SOCKET_TYPE_STREAM, 0);
local.sin_port = htons(80);
bind(socket_handle, &local, sizeof(local));
listen(socket_handle, 5);
printf("Ready to accept HTTP connections...\r
");
// here is the main loop of the HTTP server
while (1)
{
new_socket_handle = accept(socket_handle, &address, sizeof(address));
handleRequest(new_socket_handle);
closesocket(new_socket_handle);
}
注意當(dāng)接收到一個(gè)新的socket時(shí),這一簡(jiǎn)易應(yīng)用程序不會(huì)啟動(dòng)一個(gè)新的線程或進(jìn)程處理該請(qǐng)求,而是在同一進(jìn)程中處理請(qǐng)求。任何優(yōu)于該演示的HTTP服務(wù)器都會(huì)在一個(gè)新的線程中處理到來(lái)的請(qǐng)求,允許同時(shí)發(fā)生多個(gè)連接并能進(jìn)行處理。請(qǐng)求處理完畢后我們關(guān)閉socket并等待下一個(gè)到來(lái)的連接。
handleRequest方法從接入的請(qǐng)求中解析出文件名并且驗(yàn)證請(qǐng)求方法為GET。不允許使用其它方法(即使是POST、HEAD或OPTIONS)。
為IAR編譯器編寫(xiě)DS80C400匯編函數(shù)的注意事項(xiàng)
IAR文檔提供了在8051匯編中編寫(xiě)程序,可從C程序中調(diào)用的方法。若8051匯編函數(shù)由IAR編譯器編寫(xiě)的C程序來(lái)調(diào)用,在編寫(xiě)這些匯編語(yǔ)言時(shí)需切記以下幾點(diǎn)。如果沒(méi)有可用的寄存器傳遞變量時(shí),會(huì)將這些變量以Little Endian順序壓入堆棧。
函數(shù)參變量傳遞約定
下表說(shuō)明了變量的傳遞方式。ArgumentsCharacter
8-bit valuesR1,R2,R3,R4,R5
16-bit valuesR3:R2 or R5:R4
24-bit (pointer) valuesR3:R2:R1
32-bit valuesR5:R4:R3:R2
下表顯示了函數(shù)返回值的規(guī)則。ArgumentsCharacter
8-bit valuesR1
16-bit valuesR3:R2
24-bit (pointer) valuesR3:R2:R1
32-bit valuesR5:R4:R3:R2
函數(shù)int foo(int x, int y,void* ptr);的變量和返回值的傳遞如下:
?
數(shù)據(jù)類(lèi)型存儲(chǔ)規(guī)則
IAR遵循Little Endian存儲(chǔ)規(guī)則。注意,IAR使用最低有效字節(jié)在前的二進(jìn)制數(shù)據(jù)存儲(chǔ)格式。
例如,一個(gè)4字節(jié)長(zhǎng)的數(shù)值0xDEADBEEF,將會(huì)按如下方式存儲(chǔ):
?
一個(gè)簡(jiǎn)單的匯編程序與'C'接口
本節(jié)演示如何編寫(xiě)一個(gè)匯編程序并用IAR Embedded Workbench與'C'程序接口。應(yīng)用程序交換16位和32位字節(jié),并將交換后的字節(jié)輸出到默認(rèn)的控制臺(tái)。C的可調(diào)用函數(shù)原型是int ltob( int *shortptr , long *longptr)。
本示例程序由兩個(gè)文件組成:main.c和eswap.s51。main.c調(diào)用我們用匯編語(yǔ)言編寫(xiě)的示例函數(shù)ltob()。創(chuàng)建一個(gè)新項(xiàng)目,命名為endian;添加cstartup.s51、low_level_init.s51、putchar.c文件以及Dallas Semiconductor ROM初始化庫(kù)rominit.r51。詳細(xì)資料請(qǐng)參考上述從8051 IAR Embedded Workbench開(kāi)始。
用以下內(nèi)容來(lái)創(chuàng)建一個(gè)新的main.c文件,并將該文件添加到項(xiàng)目endian中。在C中,必須聲明一個(gè)函數(shù),以便讓編譯器知道如何調(diào)用它。ltob()函數(shù)在main()之前聲明。注意在成功運(yùn)行后函數(shù)ltob()會(huì)返回'0',而且,如果任一指針為NULL則返回非零值。程序應(yīng)向控制臺(tái)輸出以下結(jié)果:
--------------------------------------------------------------------------------------------------------------------
Program output:
Set values: int= 0xdead long = 0x12345678
Converted values: int= 0xedde long = 0x78563412
-------------------------------------------------------------------------------------------------------------------
// program main.c
#include
#include
#include
int ltob(unsigned int *intptr,unsigned long *longptr);
void main()
{
unsigned long i = 0x12345678;
unsigned int k = 0xdead;
int err;
printf("set values: int=0x%x long=0x%lx
",k,i);
err = ltob(&k,&i);
if(err)
printf("Error: One of the pointers is NULL
");
else
printf("converted values: int=0x%x long=0x%lx
",k,i);
while(1)
;
}
創(chuàng)建一個(gè)新文件eswap.s51,輸入以下匯編代碼,并將它加入到項(xiàng)目endian中。這個(gè)匯編程序?qū)⑽覀兊暮瘮?shù)ltob()聲明為PUBLIC,因此它能夠由'C'程序調(diào)用。ltob()的第一個(gè)參數(shù)是指針,并通過(guò)DS80C400控制器的寄存器r3:r2:r1來(lái)傳遞。第二個(gè)參數(shù)也是一個(gè)指針,由IAR編譯器壓入偏移3至5堆棧(偏移3含有最低有效字節(jié),偏移5含有最高有效字節(jié))。首先,函數(shù)重新找到堆棧中存儲(chǔ)的指針(指向一個(gè)32位值),交換它所指向的值,將交換后的字節(jié)存儲(chǔ)在相同位置。同樣,16位值也被字節(jié)交換并存儲(chǔ)在交換前的同一位置。注意,通過(guò)匯編函數(shù)來(lái)保留寄存器r6和r7。這是因?yàn)镮AR編譯器將這些寄存器視為永久寄存器,意味著任何函數(shù)調(diào)用都不應(yīng)修改這些寄存器。
#include "reg400.inc"
r0_b0 equ 0 ; Register bank 0 equates.
r1_b0 equ 1
r2_b0 equ 2
r3_b0 equ 3
r4_b0 equ 4
r5_b0 equ 5
r6_b0 equ 6
r7_b0 equ 7
PROGRAM ENDIAN_SWAP
PUBLIC ltob
RSEG FAR_CODE:CODE:NOROOT(0)
; ********************************************************************
;
; int ltob(unsigned int* shortptr, unsigned long* longptr)
;
; ********************************************************************
ltob:
// shortptr is in r3:r2:r1
// longptr is in stack at offset 5
; get the longptr stored in the stack
mov a,SP
clr c
subb a,#5
mov b,a
mov a,esp
anl a,#0x3
orl a,#0xDC ; extended stack is at 0xff dc00
subb a,#00 ; subtract 0x0005 to point to MSB of 2 nd argument
mov DPX,#0xFF
mov DPH,a
mov DPL,b
push r6_b0 ; save r6:r7 for the compiler
push r7_b0
movx a,@DPTR
mov r4,a ;store least significant byte of 'longptr' in r4
inc DPTR
movx a,@DPTR
mov r5,a ;store middle byte of 'longptr' in r5
inc DPTR
movx a,@DPTR
mov r6,a ;store most significant byte of 'longptr' in r6
mov a,r4_b0
orl a,r5_b0
orl a,r6_b0
jz ltob_err ; is (longptr == NULL)?
mov dpx,r6_b0 ; point to the memory where 'longptr' is pointing to
mov dph,r5_b0
mov dpl,r4_b0
pop r6_b0 ; restore r6:r7 for the compiler
pop r7_b0
push dpx
push dph
push dpl
movx a,@dptr ; get the long value (in r4:r3:r2:r1) from the memory
mov r4,a
inc dptr
movx a,@dptr
mov r5,a
inc dptr
movx a,@dptr
mov r6,a
inc dptr
movx a,@dptr
mov r7,a
inc dptr
pop dpl
pop dph
pop dpx
mov a,r7_b0 ; swap the long value bytes and store it in memory
movx @dptr,a
inc dptr
mov a,r6_b0
movx @dptr,a
inc dptr
mov a,r5_b0
movx @dptr,a
inc dptr
mov a,r4_b0
movx @dptr,a
mov a,r1_b0 ; is (shortptr == NULL)?
orl a,r2_b0
orl a,r3_b0
jz ltob_err
mov dpx,r3_b0 ; point to a memory where the 'shortptr' is pointing to
mov dph,r2_b0
mov dpl,r1_b0
push dpx
push dph
push dpl
movx a,@DPTR ; get the integer value from memory
mov r2,a
inc dptr
movx a,@dptr
mov r1,a
inc dptr
pop dpl
pop dph
pop dpx
mov a,r1_b0 ; swap the integer bytes
movx @dptr,a
inc dptr
mov a,r2_b0
movx @dptr,a ; bytes of an integer are swapped and stored in memory
mov r3,#00 ; return 'success'
mov r2,#00
sjmp ltob_exit
ltob_err:
mov r3,#00 ; return 'error'
mov r2,#01
ltob_exit:
ret
END ; end of assembly program
?
局限性以及開(kāi)發(fā)問(wèn)題
以下是使用6.11A版的IAR編譯器時(shí)發(fā)現(xiàn)的局限性:
IAR編譯器用堆棧存儲(chǔ)本地變量。在DS80C400中,堆棧限制為1024字節(jié)。DS80C400庫(kù)的默認(rèn)堆棧交換為384字節(jié)(ROM_SAVESIZE) 。如果您的程序聲明了多個(gè)堆棧變量,確保該限制也適當(dāng)?shù)刈兓R淖兡J(rèn)任務(wù)的交換大小,使用Dallas Semiconductor的task_genesis(unsigned int savesize)庫(kù)或rom400_task.h中定義的task_fork(unsigned char priority, unsigned int savesize),并給savesize參數(shù)提供正確的值。
printf、sprintf等函數(shù)存在一些問(wèn)題:只有選擇了'lowest optimization level'函數(shù)才能正常工作。要選擇優(yōu)化等級(jí),找到project→options→ICC8051,并選擇Code標(biāo)簽中的'None'。
IAR printf, sprintf的默認(rèn)庫(kù)不能正常工作。要使它們正常工作,您的C程序應(yīng)包含IAR提供的C文件(如#include
結(jié)論
Dallas Semiconductor為IAR編譯器提供支持C程序訪問(wèn)DS80C400 ROM軟件的函數(shù)。用C程序能夠訪問(wèn)網(wǎng)棧、存儲(chǔ)管理器、進(jìn)程調(diào)度器以及DS80C400的其它許多函數(shù)。使用C語(yǔ)言的DS80C400微控制器開(kāi)發(fā)者能夠編寫(xiě)出更精簡(jiǎn)的應(yīng)用程序,賦予系統(tǒng)足夠的速度、能力和代碼空間。Dallas Semiconductor正致力于將所有目前工作與Keil編譯器的DS80C400庫(kù)移植到IAR。請(qǐng)經(jīng)常訪問(wèn)DS80C400 IAR庫(kù)主頁(yè)獲得升級(jí)。
評(píng)論
查看更多