Using the SDCC compiler for the DS80C400
The DS80C400 contains a ROM that provides a network stack, memory manager, and process scheduler that is flexible enough to be used from applications written in Java, C and 8051 assembly. SDCC provides a free, open-source compiler for 8051 devices that is compatible with the 24-bit addressing mode of the DS80C400. Complicated applications written in C can be easily built using the features of the DS80C400 ROM with the assistance of libraries provided by Dallas Semiconductor. These libraries, along with documentation and example code, are available for download.
This application note describes how to use the SDCC tools to build applications for the DS80C400. It begins with a HelloWorld application, and then demonstrates how to make use of the ROM libraries to implement a simple HTTP Server. The applications here are written and built for use with the TINIm400 reference module, and must be modified for designs with other memory configurations.
Introduction
Getting Started with the SDCC Compiler
- Install SDCC compiler¹
- Download the installation file for the latest SDCC compiler version from SDCC website.
- Follow the instructions of setup file (possibly sdcc/doc/INSTALL.txt).
- Create a new file "main.c" using your favorite text editor. Write the following in that file:
#include <stdio.h> void main () { printf("Hello Universe!!!!....Welcome to SDCC Tini Test Program"); while (1) { } }
Make sure to save the contents of this file. - Copy the files startup400.a51 and reg400.inc (included in the startup code download) from the SDCC C Library Website² to the same directory where you stored main.c. This file contains the startup_code function that will be called on application startup to initialize the DS80C400 chip. The startup code does the following:
- Configures DS80C400 in 24-bit contiguous address mode
- Configures timer 2 to generate 115200 baud rate for serial port
- Initializes the data memory
- Copy and unpack the ROM initialization library files(rominit.lib and rom400.h from the init library download) from SDCC C library website to the same directory. The library distribution is zipped, so use WinZip or gunzip/tar to open the package.
- Before we compile our "Hello Universe" application, we need to make a small change in one of the SDCC-installed support files to override the default DS80C400 support functions and use Dallas Semiconductor's C library instead. Make the following changes:
- Rename \SDCC\lib\ds400\libds400.lib file to \SDCC\lib\ds400\libds400.lib.old
- Create an empty \SDCC\lib\ds400\libds400.lib file (use the touch command or create a blank file in your favorite text editor)
- Build the "Hello Universe" application...
- To create an object file (.rel) from our startup400.a51 file, execute the following from the command line:
asx8051 -losffgp startup400.a51
asx8051 is the assembler provided with the SDCC tools. The options provided to the assembler are: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 The "los" option is mandatory, as the linker requires list, object and symbol files to generate executables. The "ff" and "p" options generate a readable list file. The "g" option tells the assembler to not generate an error if it finds an undefined symbol that is not declared as external. - To create an object file from main.c, execute the following:
sdcc -c -mds400 --model-flat24 --stack-10bit --no-xinit-opt main.c
sdcc is the compiler. The options passed to the compiler are: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
Note the double dashes on the last three arguments in the table. - To link the object files and build the executable, run the following:
sdcc -mds400 --model-flat24 --stack-10bit -Wl-r --xram-loc 0x10000 --xram-size 0x3fff --code-loc 0x400000 main.rel startup400.rel -l rominit.lib
The new options used here are: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 Note the double dashes on the xram-loc, xram-size, and code-loc arguments. Also note that the RAM specified to the command will be used for SDCC variable storage, and should not conflict with the memory range used in the init_rom function to initialize the DS80C400--that memory is used for the network stack and memory manager. - To compress the executable file and generate a hex file, execute the following:
packihx main.ihx>hellouniverse.hex
The packihx utility compresses the executable file by accumulating contiguous data records up to 16 bytes.
- To create an object file (.rel) from our startup400.a51 file, execute the following from the command line:
Loading the Sample Application onto the TINIm400 Module

Figure 1. MTK options on startup.

Figure 2. Selecting the TINIm400 configuration option.
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 >
> B40 > X
> E
.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
Interfacing to the ROM and SDCC ROM Libraries
- ROM initialization Routines
- DHCP Client
- Process Scheduler
- Sockets (TCP, UDP, Multicast)
- TFTP Client
- Utility functions (CRC16, random numbers)
A Simple Application: HTTP Server
The SNTP Client Module
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);
The Simple HTTP Server
struct sockaddr local; unsigned int socket_handle, new_socket_handle, temp; socket_handle = socket(0, SOCKET_TYPE_STREAM, 0); local.sin_port = 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); }
A Note About Writing DS80C400 Assembly Functions for SDCC Compiler
- Function Parameter passing convention:
The following table shows how arguments are passed for reentrant functions
Argument position Character Integer Long Address First argument Dpl Dph:dpl B:dpx:dph:dpl B:dpx:dph:dpl Second argument onwards the values will be passed through hardware stack from right to left The arguments for the function void sample_func(long x, long y,int z) reentrant; will be passed as follows. - Data type storing convention:
SDCC follows the Little Endian storing convention. In other words, SDCC uses the format for storage of binary data in which the least significant byte appears first. For example, a 32-bit long value 0xDEADBEEF will be stored as follows: - Address pointer size
SDCC uses four bytes for storing memory addresses. The following table shows the format of memory address:
Most significant byte 3rd byte 2nd Byte Least significant byte address type (possible values for ds80c400: 0-near, 1-far, 2-code) MSB of address 2nd byte of address LSB of address
Limitations and Development Issues
- The compiler does not support recursive functions
- The library routines are not optimized.
- The assembler does not support macros
- Functions like printf and sprintf have some issues and would not work properly for some parameter combinations. For example, the following code causes the application to hang:
char temp[50]; sprinf(temp,"%d",234234);
- Arithmetic expression with long constants are not working properly
- The assembly code generated for array initialization (‘int[] values={1, 2, 3, 4, 5};') does not initialize the correct memory area.
Conclusion
Relevant Links
Notes
¹ Download the SDCC compiler² Java runtime environment
3 Java communications API