Programming notes - SC12 @CHIP-RTOS V1.10
IPC@CHIP Documentation Index
- Here are some useful notes for programming applications for the IPC@CHIP.
These notes contains general rules for programming DOS applications for the IPC@CHIP
and important information about internals of the @CHIP-RTOS which
can prevent the programmers from making fatal errors.
Common notes for building IPC@CHIP user applications
Limited Flash Write Cycles (of IPC@CHIPs internal Flash):
To open files on the flash disk drive A: for reading or writing, you can use the
standard C functions fopen or open.
We recommend the use of the fopen/fread/fwrite calls instead of open/read/write to reduce
the flash write cycles, because these cycles are limited.
For further information see the FlashWriteCycles
- Compiler option settings:
We recommend the usage of large memory model for user applications.
The compiler must produce 186 processor instruction code.
The data alignment must be set to 8 Bit (Byte alignment), not to 16-Bit (Word alignment)!
No "exception handling" at Borland C 4.x or 5.x projects:
Users of Borland C-Compilers (which provides "exception handling libraries"
as it's default setting for 4.5 or 5.02) should choose for their program
project "No exceptions" at the "Target Expert" window.
This setting saves Flash and RAM memory space.
Do not select "Test stack overflow" at Borland C 4.x or 5.x project compiler settings:
If "Test stack overflow" is selected a stack check is done at every function call. If stack overflow
is recognized the program halts.
This mechanism is not usable in user applications which are using several tasks inside their application,
because every task has its own stack and the Borland runtime library stack functions are not
aware of this.
- Turbo Pascal programmers should include the example file SC12.INC (part of each
IPC@CHIP Pascal example program).
At the start of their program, they should install the procedure Terminate_Program
as the default exit procedure of the program.
Usage of the standard unit crt is not allowed.
- Before starting the first Turbo Pascal program at the IPC@CHIP the
memopt 1 command must be executed
(e.g. in the autoexec.bat)
- If programs that depend on one another are started from a batch file (e.g. if a user
program needs a previous driver program) the Batchmode 1
in chip.ini should be set.
- The old CLIB library (< V2.00) and some older examples are using the standard int86 and int86x
calls from the Borland C standard
library. We used these functions for more readable code. If developers need higher performance
in their applications,
it will be better to use the new CLIB library (>= V2.00) which implements the API calls with inline assembler code. With
inline assembler instructions it is possible to load the processor registers directly with the needed
parameters and directly invoke the appropriate software interrupt int xxh.
- For certain reasons it is not advisable to design an IPC@CHIP application as a set of several DOS programs:
1. It is more meaningful to run several tasks (built with the RTOS API) inside of one DOS program because this requires
much less RAM and Flash memory space, than running several DOS programs as tasks of the @CHIP-RTOS.
2. It can lead to high memory fragmentation and insufficient memory, if more than one or two DOS programs
are running on the IPC@CHIP, which will be often terminated and restarted again.
- Most of the used pointer variables and function parameters in the old CLIB library C
files (< V2.00) are not declared as FAR pointer, because all of our test programs are using
the memory model Large (at model Large all pointers become automatically FAR pointers).
If you want to use e.g. memory model Small for your application you should use the new CLIB (>= V2.00)
and declare the pointer variables and function parameters inside your program explicit as FAR pointers.
It is not advisable to use in your application the Borland C-library malloc function
with memory model Large.
In that case the DOS program tries to increase its own memory block with
If another program is loaded after that program the malloc call fails,
because there is no memory space left between the two programs.
It is possible to define a memory gap between two loaded programs at
but then you must know what maximum memory is required by your malloc calls.
It is better to reserve inside of your application the memory by declaring an unsigned char array
(or the type you require) with the needed memory size.
The @CHIP-RTOS has its own memory strategy.
The @CHIP-RTOS always allocates memory in the following way:
DOS programs are always loaded at the first lowest free memory block.
For memory blocks allocated inside of the @CHIP-RTOS or e.g. with
DOS service 0x48 the @CHIP-RTOS
always start searching for a free memory block from the highest possible RAM address.
So the largest free memory block of the system is always located in the
middle of the @CHIP-RTOS memory area.
The shell command mem shows the state of the internal memory map.
Top of list
Using RTOS API
- Timer procedures must be implemented as short as possible, because they are executed in the Kernel task.
Large timer procedures are blocking the kernel and other tasks of the @CHIP-RTOS.
Do not use large Clib functions like printf inside of a timer procedure.
This can cause a fatal stack overflow in the kernel task (stack size 1024 Bytes)
- Declaring of timer procedures with Borland C:
void huge my_timer(void)
- Microsoft C:
void far _saveregs _loadds my_timer(void)
- Turbo Pascal:
[... your code ...]
(* This is needed at the end of the Timer Proc. *)
- DOS applications are running as a task of the @CHIP-RTOS with a default priority of 25.
If the users application doesn't go to sleep, lower
priority tasks like the FTP server or the Web server will not work.
In major loops within user applications, the programmer should insert
sleep calls if the FTP server
or Web server should work during the runtime of the user application.
- The stack of a task created inside of a DOS application
should have a minimum stack size of 1024 Bytes.
Programmers of task functions who are using Microsoft C-Compilers with C-Library functions,
e.g. sprintf, which requires a lot of stack space should increase this
allocation to 6144 (6 Kbytes). More stack space for the task is also required
if your task function uses a large amount of stack for automatic data (local variables) declared
inside the task function call.
- Declaring of task functions with Borland C:
void huge my_task(void)
- Declaring of task functions with Microsoft C:
void far _saveregs _loadds my_task(void)
- Before exiting an application, every task or timer procedure created inside of this application program
must be removed.
- A sleep call with parameter 1 millisecond takes
equal or less than one millisecond.
If a user needs a minimal sleep time of 1 millisecond then RTX_SLEEP_TIME must be called with value
- It is possible to create tasks with a time slicing value
in the taskdefblock structure..
Please note that the kernel executes time slicing only between tasks which have same priority.
Other priority tasks are not affected.
Top of list
Programming CGI functions
- Avoid large loops inside of CGI functions. CGI functions must be executed
as fast as possible. Large execution times in CGI functions block
the Web server task preventing response to other http requests.
- Declaring of CGI functions with Borland C:
void huge my_cgi_func(rpCgiPtr CgiRequest)
- Declaring of CGI functions with Microsoft C:
void far _saveregs _loadds my_cgi_func(rpCgiPtr CgiRequest)
- Declaring of CGI functions with Borland Turbo Pascal:
- Turbo Pascal users must install their CGI functions with API call
Install CGI Pascal function
- C-Programmers must use Install CGI function
- Avoid the declaration of large arrays as local variables inside
of the CGI function to prevent stack overflows
- Users of Microsoft C should set Web server stacksize in
chip.ini up to 6144 KBytes,
to prevent stack overflows, if Microsoft CLib functions like sprintf are used.
- Dynamic HTML or text pages, which are created inside of a user CGI function should be as
small as possible. The Web server inside must allocate
a temporary buffer for storing this page before sending it to the browser. If your application builds
large dynamic HTML page in RAM, your application should not use all available memory in the IPC@CHIP
because the Web server will need some memory for allocating temporary buffers for this
page. How much memory should be left: This depends on the application and the sizes
of the created dynamic HTML or CGI pages.
- Before exiting an application, every CGI function installed by the application must be removed
with Remove CGI page
Top of list
Configure the FTP server
- The default FTP idle timeout is set to 300 seconds. This is a very long time for waiting,
if FTP commands fail.
The idletimeout can be reduced in chip.ini.
Top of list
Usage of the TCP/IP API
- Processing of a socket callback functions (see Register callback)
should be kept at a minimum to prevent stack overflows.
- Declaring of socket callback functions with Borland C:
void huge my_callback(int socketdescriptor, int eventflagmask)
- Declaring of socket callback functions with Microsoft C:
void far _saveregs _loadds my_callback(int sd, int eventmask)
- The internal TCP/IP stack of the IPC@CHIP allocates memory for buffers smaller than 4096 bytes
from a pre-allocated memory block.
Larger buffers are allocated direct from the CHIP-RTOS. If user TCP/IP network
packets with a size larger than 4096 bytes, the user application should not use
all available memory in the IPC@CHIP because of these additional allocations. There should be
in that case always a minimum of 30-40 KBytes of free available memory in the IPC@CHIP.
The mem command shows the whole memory list
of the IPC@CHIP at runtime. The maximum amount of TCP/IP memory can be configured
at chip.ini (see Set TCP/IP memory size).
The application programmer can reduce or increase this size in chip.ini.
With the API call Get TCP/IP memory info it
is possible to control the TCP/IP memory usage at the application runtime.
Top of list
General notes for the usage of the DOS and @CHIP-RTOS int API calls
- At the start of a user program the Stdio focus should be set to USER.
Before ending the application switch the focus back to SHELL or BOTH
(see Set Stdio focus).
- If more than one user program runs in the IPC@CHIP, only one of them should
read characters from Stdin
- The functionality of most of the shell commands is also available through calls into the
@CHIP-RTOS INT API. If not, use
the @CHIP-RTOS INT call Execute a shell command.
This call executes a shell command from inside the user application.
- Install a fatal user error handler, which does a reboot of the IPC@CHIP with
Install user fatal error handler
- Used software interrupts (all others are free for use):
0x00 - Reserved (@CHIP-RTOS Divide Overflow Handler)
0x01 - Reserved (Debugger Trace Interrupt)
0x02 - Reserved (Hardware Non-Maskable Interrupt (NMI))
0x03 - Reserved (Debugger Breakpoint Interrupt)
0x04 - Reserved (@CHIP-RTOS INTO Overflow Handler)
0x05 - Reserved (@CHIP-RTOS Array Bounds Exception Handler)
0x06 - Reserved (@CHIP-RTOS Invalid Opcode Exception Handler)
0x07 - Reserved (@CHIP-RTOS ESC Opcode Exception Handler)
0x08 - Reserved (Hardware, Timer #0 Handler)
0x0A - Reserved (Hardware, DMA #0 / INT5 Handler)
0x0B - Reserved (Hardware, DMA #1 / INT6 Handler)
0x0C - Reserved (Hardware, INT0 Handler)
0x0D - Reserved (Hardware, INT1 Ethernet Handler)
0x0E - Reserved (Hardware, INT2 Handler)
0x0F - Reserved (Hardware, INT3 Handler)
0x10 - Biosint
0x11 - Biosint
0x12 - Reserved (Hardware, Timer #1 Handler)
0x13 - Reserved (Hardware, Timer #2 Handler)
0x14 - Fossil Interface
0x16 - Biosint
0x1A - Biosint
0x1C - Timer Interrupt, see Set timer 1C interval
0x20 - Terminate Program (Only for compatibility, instead use
DOS service 0x4C)
0x21 - DOSEmu Interrupt Interface
0xA0 - Several 'chip' related services
0xA1 - Hardware API (HAL)
0xA2 - Hardware API (PFE)
0xAA - I2C Interface
0xAB - CGI Interface
0xAC - TCP/IP API
0xAD - RTOS API
0xAE - Ethernet Packet Driver
0xAF - Timer Interrupt, see Set timer AF interval
0xB0 - External Disk API
0xB1 - External Disk Driver
0xBF - This vector is reserved to start a DOS executable
If you are using a BIOS variant in which some modules are not included, then the interrupts
corresponding to these modules are free for use.
- External hardware interrupts are enabled (STI opcode) during execution of the
following API software interrupts:
DOS ints 0x10, 0x14(Fossil), 0x16, 0x20, 0x21, @CHIP-RTOS int 0xA0, CGI int 0xAB, PFE int 0xA2,
I2C int 0xAA, CGI int 0xAB, Pkt int 0xAE, Extdisk int 0xB0, Extdisk user int 0xB1
The state of the interrupt flag is not changed during the execution on the following API software interrupts
(If interrupts are disabled before the API call, they are kept disabled during execution of the call.
If interrupts are enabled before the API call, they get reenabled during execution of the call.):
TCPIP int 0xAC, RTOS int 0xAD
External hardware interrupts are disabled during execution of the
following API software interrupts:
HAL int 0xA1
Top of list
Using Hardware API
- The HAL functions keep interrupts disabled, so you can call them inside an
interrupt routine. The PFE functions are only for choosing and initializing a
specific function on the selected pin. They should be called once in your
application for initializing your hardware environment and not at runtime or
inside interrupt routines.
Do not use functions of the RTOS API inside of a normal HW API user ISR.
For this purpose install a RTX user ISR, see Install ISR.
- The latency time of the user ISR (from generation of an interrupt until
first line of code inside the user ISR) depends on the used IPC@CHIP, see
Performance comparision .
- Instead of HAL functions Read data bus
and Write data bus you can call C-functions
inportb and outportb from DOS.H for faster data bus accesses.
- Usage of DMA0/INT5 and DMA1/INT6:
DMA0 and INT5 are served inside the @CHIP-RTOS with a single shared interrupt handler.
(Likewise for DMA1 and INT6.)
If an user application has activated serial EXT DMA mode
and also wants to use external interrupt INT5, the DMA interrupt event is higher priority. (And
again, likewise for COM DMA mode and INT6.)
This means that if a DMA0/1 interrupt occurs simultaneous with an external INT5/6 interrupt,
the installed user handler for the external interrupt is not called.
See Hardware API
- Usage of NMI/Power fail detection:
The NMI function of the multifunction pin 17 (RESET/NMI/LINK_LED)
of the IPC@CHIP SC11/SC12/SC13 is for power fail purposes only.
It is not possible to use NMI as a "normal" interrupt pin like e.g. INT0 for generating interrupts.
It can only be used as described in the IPC@CHIP hardware documentation.
The flowchart below describes how the @CHIP-RTOS handles an incoming NMI interrupt.
Install interrupt service routine
Init non-volatile data
Save non-volatile data
Top of list
Using Fossil API
- The receive and send queue size
can be configured over the CHIP.INI.
- If you want to use external DMA, you have to disable the
serial DMA receive mode.
Otherwise the DMA receive mode is recommended.
- Since @CHIP-RTOS 1.02B XON/XOFF mode is available also with the serial DMA receive mode in use.
Please note: Because of the internal functionality of DMA it is not
possible to immediately detect an XON or XOFF character from the connected peer. It is possible that
an overrun situation at the peer (e.g. GSM modem) can occur.
Nevertheless we enable this mode because some GSM modems (any??) support only XON/XOFF as
serial flow control mechanism.
- The default serial receiver queue size is 1024 bytes. If the default DMA receive mode is used,
it is advised to increase the receiver queue size in
up to a minimum value of 2048 bytes to prevent a possible buffer overrun
(even if hard handshake is used).
This can only happen with the default queue size of 1024 bytes if the user doesn't call the
Fossil API read block function
If the application programmer does not increase this buffer size up to the
recommended value, they should call the
Fossil API read block function
with sufficient buffer size
in the CX-Register to flush the internal buffers and prevent a receive buffer overrun.
Serial ports, running with IRQ receive mode:
The two serial ports of the IPC@CHIP have no hardware FIFO buffer. Only one incoming
character can be stored direct by the ports.
As a consequence of this behaviour, it is possible that incoming characters get lost because
of missed or delayed receiver interrupt execution
(see Operating mode of serial ports).
E.g.: Writing a flash sector (e.g. happens when writing a file at Drive A:)
disables all interrupt execution for about 15 ms. If the serial port is configured with
a baud rate of 9600, incoming characters can be lost during this time.
Loss or delayed execution of serial receiver interrupts depends on the number
and the execution frequency of all enabled interrupts in the IPC@CHIP system.
It depends also on execution times of users interrupt service functions and the duration of
interrupt masking periods (CLI / STI instruction sequences).
- For a given serial port the fossil functions are not reentrant. Do not call fossil functions for
the same serial port from different tasks. However for different serial ports, the fossil functions
are reentrant. E.g. task A can operate the COM port using fossil functions concurrently with task
B operating the EXT port using the same fossil functions.
Top of list
Working with Float Data Types
- The IPC@CHIP does not provide a floating point co-processor. So if you want to use floating point data
types you need to enable the math-emulation in your compiler. In Borland C++ 5.02 see the option
"Emulation" under the Target Expert's
(right mouse click on your Exe-file in your project) "Math Support".
- The Borland Math Emulation libraries are not made for usage in a multitasking system like the @CHIP-RTOS.
If you want to use float data types in tasks other than your main (DOS) task, please pay attention to the
following work around solution (Using Borland 5.02, Memory model large):
a) For floating point emulator usage, the current stack (the stack of the task) must have offset 0.
To achieve this, the task stack must be far array located in a separate segment:
unsigned int far task_stack[TASK_STACKSIZE];
Note: The CGI callbacks execute on the Web server's stack, which satisifies this "offset
0 present" requirement.
b) The current stack must be pre-initialized for math emulation:
mov word ptr ss:[0x2f],0x0065 // set end of FPU stack
mov word ptr ss:[0x31],0x0125 // set start of FPU stack
mov word ptr ss:[0x27],0 // no protected mode
mov byte ptr ss:[0x26],0 // no 8087
c) Before executing floating point arithmetic, call the Borland library
function _fpreset, which
initializes the stack for floating point emulation.
Example for a task function:
void huge my_task(void)
// ..... ready for executing floating point arithmetic
If you are interest in more details, take a look at the Borland 5.02 RTL sources
We will provide an example for using floating point arithmetic in separate tasks
or within CGI callbacks.
Using Math emulation with Borland C++ 5.02 (also for older versions of Borland C) produces a conflict between
the NMI interrupt of the @CHIP-RTOS (Interrupt Vector 0x02) and the Borland floating exception handling.
Borland C math emulation also uses INT 2 for generating floating point exceptions.
Our internal NMI interrupt service function (normally called at power fail case) will no longer execute
during the runtime of the user's application.
We have provided a solution which moves the Borland exception function from
INT 2 to another interrupt vector.
We modified the Borland RTL source (fpinit.asm) and include the modifications directly
into the application project.
It is planned to provide an example in our Internet download area.
Top of list
Configure PPP client or server
Connected modems should be configured in chip.ini with the modem command ATE0
This prevents the modem from echoing characters to the peer in command mode.
The COM and the serial ports of the IPC@CHIP have only 4 lines (TxD/RxD/CTS/RTS) and no line for
detecting a hang-up of the modem. Because of this fact we provided the
the MODEMCTRL configuration features in chip.ini
or in the PPP client init structure type.
But the idletimeout and modemctrl detection can fail
if a modem has switched its echo mode on.
If the peer modem hangs up without correctly closing a PPP session, the IPC@chip modem also hangs
up and goes into the command mode.
Because of the missing line for detecting a modem hang-up, the PPP server doesn't know anything about
the broken connection and still sends PPP frames to the modem. It can happen that the modem
echoes these characters back to the IPC@CHIP due to being in "Echo on" mode. This will cause the
idletimeout to not work.
- We recommend that the PPP server or client and the connected modems should run (if possible)
with RTS/CTS flow control
(see chip.ini flow control mode or the
PPP client init structure type).
Most modems use RTS/CTS flow control, if they get the AT command AT\Q3.
The COM and EXT port of the IPC@CHIP has only CTS, RTS, RxD and TxD lines,
so you have to configure your modem with DTR always on.
(e.g. AT cmd for a most modem types: AT&D0)
- If the option PPP_IPCP_PROTOCOL (VJ TCP/IP header compression) is set (see
it is possible that the FTP server of the IPC@CHIP is not usable via the PPP interface.
This was noticed at PPP sessions connected to a Linux PPP peer.
Top of list
End of document