要約:DS80C400マイクロコントローラのROMの機能には、8051アセンブリ、C、またはJava™で記述されたプログラムからアクセスすることができます。このROMとダラスセミコンダクタが開発したソフトウェアライブラリを使用することによって、多くのアプリケーションを構築することができます。このアプリケーションノートでは、8051 IAR Embedded Workbench™を使用して、DS80C400向けのアプリケーションをCで構築する方法について説明します。簡単なHTTPサーバを実装することによってDS80C400のROMの機能を説明します。
このアプリケーションノートでは、8051 IAR Embedded Workbenchを使用し、CでDS80C400用のアプリケーションを構築する方法について説明します。また、簡単なHTTPサーバを実装することによってDS80C400のROMの機能を使用する方法についても実際に説明します。ここで説明した開発はすべて、TINIm400検証モジュールと8051 IAR Embedded Workbench (Cコンパイラのバージョン6.11Aを同梱)を用いて行いました。
[Project][Create New Project]の順に選択します。表示されるダイアログボックスにプロジェクトの名前「hellowworld」を入力します。8051がツールチェーンとして選択されていることを確認します。
プロジェクトウィンドウが左に表示されたら、[Project][Add Files...]の順に選択します。ポップアップダイアログボックスで、[files of type]を[Assembler Files]に変更します。Cstartup.s51というファイルを追加します。このファイルは、ZIPファイルです:ダウンロード。
ファイルCstartup.s51をダブルクリックして開きます。セグメント宣言RSEG CSTART:CODE:ROOT (0)を見つけます。ここはコードセグメントが開始される場所です。各セグメントの開始アドレスはファイルlink51ew_400.xclで宣言されています。コードの開始は、このファイルの0 × 400000hで宣言されています。また、「DB 'TINI'」という行、およびこれに続いて、「Target Bank」というコメントが付いた「DB, high (?INIT)'」行があるはずです。これによって、アプリケーションは、TINIm400上のフラッシュの先頭と一致することになります。
新しいファイルmain.cを作成します。このファイルに以下の内容を記述します:
#include <stdio.h>
#include <printf.c>
void main ()
{
printf("Test program using IAR compiler");
while (1)
{
}
}
ROM initializationライブラリファイルをhttp://files.dalsemi.com/tini/ds80c400/c_libraries/iar/bin/init.zipから同じディレクトリにコピーし、解凍します。rominit.r51ライブラリファイルをプロジェクトに追加します。
[TINI]を選択すると、MTKのメインウィンドウが開きます。[Options][Configure Serial Port]メニューオプションから、TINIm400との通信に使用するシリアルポートを選択します。次に、[Tini][Tini Options]メニュー項目を選択すると、以下のダイアログボックスが表示されます。[DSTINIm400]ボタンを選択し、TINIm400ボードと通信することができるようにMTKを構成します。図5に、このダイアログと[DSTINIm400]ボタンを示します。
DS80C400 Silicon Software - Copyright (C) 2002 Maxim Integrated Products
Detailed product information available at http://www.maxim-ic.com
Welcome to the TINI DS80C400 Auto Boot Loader 1.0.1
>
アセンブリからROM関数を呼び出すプロシージャは、「高速マイクロコントローラユーザガイド」のDS80C400の付録3で説明されています。ただし、CからのこれらのROM関数の呼び出しはやや複雑です。パラメータをIAR C コンパイラの形式からROM形式に変換する必要があります。IARコンパイラは、ハードウェアのスタック位置とレジスタの組み合わせでパラメータを渡します。ところが、ROM関数はさまざまな形式でパラメータを受け取ります。たとえば、ソケット関数は1つのパラメータバッファに保存されたパラメータを受け取ります。逆に、ユーティリティ関数の多くは特殊な関数レジスタまたはスタックメモリ位置で渡されたパラメータを受け取ります。IARの呼び出し形式からROMのパラメータ形式に変換するため、ダラスセミコンダクタはROM関数にアクセスするためのROMライブラリを用意しました。
次は、リクエストのオプションを設定する行です。各ビットの意味は、RFC 1361の3節に記載されています。0x23という値は、うるう秒に対する警告なしとNTPバージョン4の使用をリクエストし、モードが「Client」であることを示すものです。共通データグラム関数であるsendtoとrecvfromを使用してリクエストを送出して応答を受信したら、タイムスタンプ値の秒の部分がtimeStamp変数に割り当てられ、基準時刻の1970年1月1日に対して時刻が調整されます。その後、formatTimeString関数を使用して、このタイムスタンプを「In London it is 05:33:19 on May 11, 2005.」などの読みやすい文字列に変換します。
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);
}
簡単なアセンブリプログラムと「C」とのインタフェース
この項では、IAR Embedded Workbenchによる、アセンブリプログラムの記述方法と「C」プログラムとのインタフェース接続の方法について説明します。アプリケーションは16ビット値と32ビット値のバイトをスワップし、スワップしたバイトをデフォルトコンソールに出力します。Cで呼び出し可能な関数のプロトタイプはint ltob( int *shortptr , long *longptr)です。
サンプルアプリケーションは、main.cおよびeswap.s51という2つのファイルで構成されています。main.cはアセンブリ言語で作成したサンプル関数ltob()を呼び出します。新しいプロジェクトendianを作成します。次に、cstartup.s51、low_level_init.s51、putchar.cの各ファイルとダラスセミコンダクタROMの初期化ライブラリrominit.r51を追加します。これについては、上記の項「8051 IAR Embedded Workbenchのインストール」で説明したとおりです。
--------------------------------------------------------------------------------------------------------------------
Program output:
Set values: int= 0xdead long = 0x12345678
Converted values: int= 0xedde long = 0x78563412
-------------------------------------------------------------------------------------------------------------------
// program main.c
#include <stdio.h>
#include <printf.c>
#include <frmwri.c>
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)
;
}
#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
IARコンパイラはスタックを使用してローカル変数を保存します。DS80C400では、スタックは1024バイトに制限されています。DS80C400ライブラリのデフォルトのスタックスワップサイズ(ROM_SAVESIZE)は384バイトです。アプリケーションが多くのスタック変数を宣言している場合は、それに合わせてこの制限を変更するようにしてください。デフォルトのタスクスワップサイズを変更するには、task_genesis(unsigned int savesize)またはtask_fork(unsigned char priority, unsigned int savesize)というダラスセミコンダクタのライブラリ(rom400_task.hで定義されています)を使用し、savesizeパラメータに適正な値を設定します。