As usual on embedded systems you have to provide your own getchar() and putchar() routines. SDCC does not know whether the system connects to a serial line with or without handshake, LCD, keyboard or other device. And whether a lf to crlf conversion within putchar() is intended. You'll find examples for serial routines f.e. in sdcc/device/lib. For the mcs51 this minimalistic polling putchar() routine might be a start:
void putchar (char c) {
while (!TI) /* assumes UART is initialized */
;
TI = 0;
SBUF = c;
}
The default printf() implementation in printf_large.c does not support float (except on ds390). To enable this recompile it with the option -DUSE_FLOATS=1 on the command line. Use --model-large for the mcs51 port, since this uses a lot of memory.
If you're short on code memory you might want to use printf_small()
instead of printf(). For the mcs51 there additionally
are assembly versions printf_tiny()
(subset of printf using less than 270 bytes) and printf_fast()
and printf_fast_f() (floating-point
aware version of printf_fast) which should fit the requirements of
many embedded systems (printf_fast() can be customized by unsetting
#defines to not support long variables and field widths).
Be sure to use only one of these printf options within a project.
Feature matrix of different printf options on mcs51.
mcs51 | printf |
printf USE_FLOATS=1
|
printf_small
|
printf_fast |
printf_fast_f
|
printf_tiny |
---|---|---|---|---|---|---|
filename | printf_large.c |
printf_large.c
|
printfl.c
|
printf_fast.c |
printf_fast_f.c
|
printf_tiny.c |
''Hello World'' size
small / large |
1.7k / 2.4k |
4.3k / 5.6k
|
1.2k / 1.8k
|
1.3k / 1.3k |
1.9k / 1.9k
|
0.44k / 0.44k |
code size
small / large |
1.4k / 2.0k |
2.8k / 3.7k
|
0.45k / 0.47k (+ _ltoa)
|
1.2k / 1.2k |
1.6k / 1.6k
|
0.26k / 0.26k |
formats | cdiopsux |
cdfiopsux
|
cdosx
|
cdsux |
cdfsux
|
cdsux |
long (32 bit) support | x |
x
|
x
|
x |
x
|
- |
byte arguments on stack | b |
b
|
-
|
- |
-
|
- |
float format | - |
%f
|
-
|
- |
%f3.9
|
- |
float formats %e %g | - |
-
|
-
|
- |
-
|
- |
field width | x |
x
|
-
|
x |
x
|
- |
string speed3.10,
small / large |
1.52 / 2.59 ms |
1.53 / 2.62 ms
|
0.92 / 0.93 ms
|
0.45 / 0.45 ms |
0.46 / 0.46 ms
|
0.45 / 0.45 ms |
int speed3.11,
small / large |
3.01 / 3.61 ms |
3.01 / 3.61 ms
|
3.51 / 18.13 ms
|
0.22 / 0.22 ms |
0.23 / 0.23 ms
|
0.25 / 0.25 ms3.12 |
long speed3.13,
small / large |
5.37 / 6.31 ms |
5.37 / 6.31 ms
|
8.71 / 40.65 ms
|
0.40 / 0.40 ms |
0.40 / 0.40 ms
|
- |
float speed3.14,
small / large |
- |
7.49 / 22.47 ms
|
-
|
- |
1.04 / 1.04 ms
|
- |
As of SDCC 2.6.2 you no longer need to call an initialization routine before using dynamic memory allocation and a default heap space of 1024 bytes is provided for malloc to allocate memory from. If you need a different heap size you need to recompile _heap.c with the required size defined in HEAP_SIZE. It is recommended to make a copy of this file into your project directory and compile it there with:
sdcc -c _heap.c -D HEAD_SIZE=2048And then link it with:
sdcc main.rel _heap.rel