After having converted 30 odd sample programs from Keil C to SDCC, here is a summary of the differences I encountered.
- Keil uses sbit to declare special bit registers using for example P0^7 to refer to port 0 bit 7. SDCC uses __sbit and a different syntax. But since most of the special registers are defined in SDCC includes, usually it suffices define your symbol to be the same as say P0_7.
- Putting large constants, e.g. tables, in the RO code area in Keil is done with the qualifier code after the type declaration, e.g. uchar code table{] = …. In SDCC it's declared thus: __code uchar table[] = ….
- Keil uses for example: interrupt 1 using 1 to qualify an interrupt service routine (ISR) as hooking to interrupt vector 1 and using register bank 1. SDCC uses the syntax: __interrupt(1) __using(1). Note that Keil makes interrupt and using unavailable for symbols. Ditto for sbit and code. Oh and remember that in SDCC the ISRs (or at least a prototype) must appear in the file containing main() or the vectors won't get initialised. This wasn't an issue for the sample programs as each was in a single C file.
- Keil has a data type called bit, usually used for booleans. I didn't see any advantage so I converted those to char (which is actually uchar for the 8051 architecture).
- The standard include in Keil C appears to be reg52.h. In SDCC it's 8051.h. Keil has additional includes like intrins.h and math.h, but these are not needed for SDCC. stdlib.h should be included if you use abs() with SDCC. stdio.h should be included if you use printf and the ilk for the serial port, and in the case of SDCC you need to implement int putchar(int) whereas it's supplied in the Keil library. If you have a MCU with more special registers then you should include the definitions for those. You may need to create your own if somebody hasn't done it already.
- Keil appears to define a special function called _nop_(). For SDCC just #define that to __asm__("nop").
- Not really a compiler difference but since Keil runs on a case insensitive OS, you can get away with #include <reg52.H> but you must respect the filename case on Linux.
- Again not a compiler difference but the sample programs often used defines like #define uchar unsigned char. I prefer to use typedefs.
- Keil lets you get away with a mix of old style and new style function headers, like int fun(int a,b), whereas you should use the standard int fun(int a, int b) in SDCC.
- In one initialisation of a structure, Keil let the programmer get away with not properly nesting braces for a struct element. It was something like this:
struct fontentry {
uchar[3];
uchar[16];
} f = { "AB", 0x00, 0x01, … };
The initialisers for the second uchar array needs to be surrounded by braces according to the standard.
If I remember any other differences I'll edit this log.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
[this comment has been deleted]
Hmm, looks like the person asking the question found their problem and deleted their question. Oh well.
Works for me. I wrote this short program:
__sbit __at(0x88+0) TCON_IT0;
main()
{
TCON_IT0 = 0;
TCON_IT0 = 1;
}
I compiled it with sdcc -mmcs51 sbit.c and looked at sbit.lst which shows that the correct instruction was generated:
131 ; sbit.c:5: TCON_IT0 = 0;
132 ; assignBit
000000 C2 88 [12] 133 clr _TCON_IT0
134 ; sbit.c:6: TCON_IT0 = 1;
135 ; assignBit
000002 D2 88 [12] 136 setb _TCON_IT0
137 ; sbit.c:7: }
So check your C program for syntax errors.
Incidentally you don't have to define TCON_IT0, there is already a special bit location called IT0 in the include file 8052.h in the SDCC distribution.
Are you sure? yes | no
Yes, I found the errors and deleted my problem post, thanks.
Are you sure? yes | no
Thanks for the useful summary :-) I've done my share of Keil C programming, and I told myself not to touch MCS51 anymore. But hey, with all the Nuvoton N76E003AT20 chips from modules converted to STM8S003F3P6 lying around I might as well solder one to a breakout board and try if SDCC MCS51 programming is any better ;-)
Are you sure? yes | no
I'd be interested in how you progress. As you may remember I investigated the Nuvoton MCS51 descendants a while back at https://hackaday.io/project/161242-board-development-for-nuvoton-n76e003 and concluded that the development tools weren't as cost effective and convenient as those for the STM8. A NU-Link programmer, similar to the ST-Link one is needed, and there is no open source equivalent to stm8flash, though the Nuvoton ICP tool works under Wine. On the other hand the STC chips can be programmed using the onboard serial loader.
Chinese manufacturers make a lot of cheap MCUs (I'm still interested in those 3¢ Padauk MCUs) but it's a pity they don't leverage the power of open software and hardware to disseminate their products wider. I guess they have a sizeable domestic market.
Are you sure? yes | no
Well, I didn't progress any further than you did - there is no open source way to replace a programmer that uses a microcontroller's 2nd UART for programming. Normally the process of recording and replaying serial data shouldn't be that complicated, provided that it's not encrypted, requires an elusive timing or actually isn't serial port data. Buying yet another programming box would maybe be OK but using a miserable Windows GUI tool for playing with those chips? Now way Jose!
Padauk: their take on building a controller is really interesting. Their IDE not. SDCC has initial support but the interesting architecture of the controller makes the task of building a standard-compliant C compiler also "interesting" :-) It might be something for Forth but the clean Harvard architecture and the lack of self-programming capabilities makes limits it to non-interactive programming.
Are you sure? yes | no
From what I understand SDCC for Padauk is closer to C than the Padauk's own offering, which is more like a glorified macro processor, doesn't even have a real for statement. I think SDCC used the same trick as for MCS51 small model, put local variables in a private static area, ruling out recursive calls, not a big loss. The freepdk devs still have to nut out the code that's tuned to each OTP unit.
Anyway enough of MCS51 for now for me. Time to pivot to other round tuits. Pandemic time can be productive time. :)
Are you sure? yes | no
Yes, SDCC is as standard compliant as it gets considering the constraints of the target. When programming something like the MCS51 the data flow gets intractable fast when a Keil-C "Fortran style" memory management approach is combined with "smart" mapping of RAM to the bit addressable IRAM area (I've worked with one old-hand programmer who had a habit of moving memory between XRAM and that area at the begin of a routine/task/whatever so that he had a choice of the addressing modes BIT, IRAM, IRAM indirect, XRAM and XRAM with the DP of the MCS51-variant-of-the-day. Try cleaning up that mess ;-)
Are you sure? yes | no