From: SourceForge.net <no...@so...> - 2006-07-11 20:43:55
|
Feature Requests item #1481734, was opened at 2006-05-04 12:14 Message generated for change (Comment added) made by frief You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=350599&aid=1481734&group_id=599 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Closed Priority: 5 Submitted By: Frieder Ferlemann (frief) Assigned to: Maarten Brock (maartenbrock) Summary: Allow: __sfr16 __at (0xcc) TMR2; Initial Comment: /* * Actually I hope this is uncontroversial * and could be pre 2.6.0 stuff? */ #define PROPER (0) #if PROPER /* * SDCC's proper and flexible way of defining * a two byte SFR */ __sfr16 __at (0xcdcc) TMR2; #else /* * If SDCC wants to share header files with * other compilers this "lazy" definition * should behave as __at(0xcdcc) */ __sfr16 __at (0xcc) TMR2; #endif void main(void){} ---------------------------------------------------------------------- >Comment By: Frieder Ferlemann (frief) Date: 2006-07-11 22:43 Message: Logged In: YES user_id=589052 I'm quite happy with the current compiler.h. ("compiler.h" is the file that allows using common header files for most 8051 C-compilers) But I don't think we are there yet: There are some devices which have Special Function Registers located in xdata memory and compiler.h does not have an abstraction for this. If we want to avoid an early "GRAB AND EXTEND" of this file we should have a macro like: # define SFRX(name, addr) xdata volatile unsigned char __at(addr) name It most likely has an impact on the acceptance (or early forking) of this file whether this file is finalized before 2.6.0 As a request for comment I'm attaching a modified compiler.h. Ooops, that file contains probably two controversial changes: a) a (non ANSI/ISO) #warning directive if the compiler is not recognized. b) changes to the macros for unrecognised compilers so that another compiler could be run over the sources. For the die-hards: you can then simulate your 8051 derivative by poking the variables corresponding to SFR in a simulator on the host... Or enjoy the warnings another compiler throws at you... I'd be happy if there is feedback (within a week). About this matter I intend to sit back, watch what the community wants and leave the final decision to Maarten:) Greetings, Frieder ---------------------------------------------------------------------- Comment By: Frieder Ferlemann (frief) Date: 2006-06-10 21:20 Message: Logged In: YES user_id=589052 thanks Maarten for the compiler.h file. - Closing the request. ---------------------------------------------------------------------- Comment By: Frieder Ferlemann (frief) Date: 2006-05-21 10:34 Message: Logged In: YES user_id=589052 > Here's my first proposal of the <compiler.h> header file. Fine - this makes my initial request obsolete:) I'm attaching a version which includes URLs for the compiler vendors and a default case for unrecognized compilers. ---------------------------------------------------------------------- Comment By: Maarten Brock (maartenbrock) Date: 2006-05-18 14:50 Message: Logged In: YES user_id=888171 Here's my first proposal of the <compiler.h> header file. I think Dunfield is impossible to support. It creates EQU's in inline assembler using $A0 to indicate hexadecimal address A0. I could also not figure out which predefined macro identifies this compiler. ---------------------------------------------------------------------- Comment By: Maarten Brock (maartenbrock) Date: 2006-05-13 15:07 Message: Logged In: YES user_id=888171 I've looked around but it's not that easy to obtain the manuals of other compilers. So I've asked a question at http://www.8052.com/forum/read.phtml?id=116161 for help from the 8052 community. GCC also has a <compiler.h> header :-) ---------------------------------------------------------------------- Comment By: Frieder Ferlemann (frief) Date: 2006-05-11 23:04 Message: Logged In: YES user_id=589052 > Do we also want to change all headers before release? Maybe we should only provide one converted header file for reference (maybe even for a device for which SDCC doesn't have a header file yet). Won't break anything, no harm is done and we could still adapt to things we have not yet thought of. > (compiler.h ?) I guess ANSI C wouldn't admit there is a need for such an include file and accordingly doesn't propose a name for it. Then compiler.h would be fine. > should make use of shifting instead of a union Yes, it should:) (the shifting versions I tried resulted in more lengthy code, so I picked the union although it is less clean. As I argued with "clean" in my example you got me there! Also in my example an "unsigned" for l is missing.) ---------------------------------------------------------------------- Comment By: Maarten Brock (maartenbrock) Date: 2006-05-11 20:18 Message: Logged In: YES user_id=888171 So now we need to write this one header file (compiler.h ?) and include it in mcu-specific headers. Do we also want to change all headers before release? You gave good arguments why not to implement my other proposal about which I had my doubts already. So let's not. B.t.w. Your put_my_sfr24 function should make use of shifting instead of a union because SDCC has an optimal GetByte implementation and shifting is portable across endianness differences. Unfortunately it's very hard to optimize putting several bytes into one word/dword. And SDCC also refuses to put any union no matter how small in registers. ---------------------------------------------------------------------- Comment By: Frieder Ferlemann (frief) Date: 2006-05-11 18:58 Message: Logged In: YES user_id=589052 > But I still think it can be done with macros. Ok, would be fine for me. Your other proposal: > ... This way you could easily access 24 bit sfr's is not:) I think it's a very tempting proposal (tempting because SDCC could relatively quickly generate compact code) but nevertheless I think we should avoid it. Because it is so tempting I thought I'd better have good arguments against it: -------------8<-------------------------------------------------------------- /* Sample code used to access 3 byte SFR If SDCC supports inlining functions this could generate efficient code. (not bad right now but not too good either) And I hope to be able to show that SDCC should *not* implement the __sfr32 __at(0x00aabbcc) and __at(0xaabbcc00) feature:) Arguments are given with the comments a) to e). I think comments a) to d) are equally valid. */ #if SDCC < 260 # define inline #endif #if !defined(SDCC_mcs51) # include <stdbool.h> # define __sfr volatile unsigned char # define __sbit bool # define __at(x) #endif __sfr __at (0xf0) MY_SFR0; __sfr __at (0xf1) MY_SFR1; __sfr __at (0xf2) MY_SFR2; __sbit __at (0xf8) MY_SFR_BUSY; __sbit __at (0xf9) MY_SFR_ACTIVATE; long result; /* Having extra functions allow to * * a) guarantee the order of access to the SFR bytes. * (so the 4 combinations of big-endian/little endian SFR * and least/most significant SFR needing to be accessed * first can be met) * * b) include some bit checking/setting in the routine * * c) make the programer aware that this an access * to a variable which might have side-effects or * which is not always valid. * Otherwise lines like: * return (ADC24 + ADC24)/2; // average * or * DAC24=100; * DAC24=200; * are easily overread. * * d) have more portable code: (portable in two aspects) * - reuse code on other compilers which do not * support the __sfr32 __at(0x00aabbcc) and * __at(0xaabbcc00) feature. * - facilitate porting the code to a (sligthly) * different derivative which needs some extra * bit handling. * Or f.e. switching to an external ADC/DAC * instead of the internal one. * * e) have a chance to insert a separation from low level * to high level code: If f.e. a CPU is offered in a * flavour with and without a 24 bit MAC unit you could * write a MAC24 emulation and keep high level code * unchanged * * So while the code below might look overly complicated * or less clean (on first sight) than an __at(0x00aabbccdd) * solution it is from my point of view a more clean solution * for embedded programming. */ static inline unsigned long get_my_sfr24() { union { long l; unsigned char c[4]; } t; while( MY_SFR_BUSY ) ; t.c[0] = MY_SFR0; t.c[1] = MY_SFR1; t.c[2] = MY_SFR2; t.c[3] = 0; return t.l; } static inline void put_my_sfr24( unsigned long val ) { union { unsigned long l; unsigned char c[4]; } t; t.l = val; MY_SFR0 = t.c[0]; MY_SFR1 = t.c[1]; MY_SFR2 = t.c[2]; /* same endianness but different order of access: MY_SFR2 = t.c[2]; MY_SFR1 = t.c[1]; MY_SFR0 = t.c[0]; */ MY_SFR_ACTIVATE = 1; } int main(void) { put_my_sfr24( 0x123456 ); result = get_my_sfr24( ); return (int)result; } ---------------------------------------------------------------------- Comment By: Maarten Brock (maartenbrock) Date: 2006-05-11 15:40 Message: Logged In: YES user_id=888171 I see what you mean. But I still think it can be done with macros. How about: #define SFR16(name, addr) __sfr16 __at(((addr+1)<<8) | addr) name; for legacy sfr16 and: #define SFR16E(name, addr) __sfr16 __at(addr) name; for SDCC Extended sfr16 functionality. I have another observation. 8051 derivatives with 24 bit sfr combinations are growing in numbers. Especially 24 bit ADC's. When I implemented sfr16 and sfr32, I also considered sfr24 but threw the idea away. I also considered sfr32 for these 24 bitters but the easy way requires there is some NUL sfr which always reads 0 and can be written anything to. For the SiLabs F350 there is none, I asked. My guess is the TI msc1210 doesn't have one either. One solution could be to extend sfr32 to accept address 0x00 as LSB or MSB address and make exceptions for that in aopGet and aopPut. This way you could easily access 24 bit sfr's as if they were (left- or right aligned) 32 bit int's. Now since sfr32 is also an SDCC unique selling point, we might do all. It only looses some built-in address- checking for sfr16/sfr32 declarations. I'm willing to take this on, but want a firm direction which way to go first. Maarten ---------------------------------------------------------------------- Comment By: Frieder Ferlemann (frief) Date: 2006-05-09 23:38 Message: Logged In: YES user_id=589052 > ... how this will help. The request won't help with the notation the "other compiler" header uses. But I think the way to go for the mcs51 are the "atmel style" macros. It is certainly in the interest of Chip vendors and users to have a common denominator. So in the long run if we provide a convenient path then "our" include files might be commonly adopted one day. SDCC's proper format requiring 2 or 4 byte SFR address information for SFR16/SFR32 allows great flexibility (we have the unique selling points of non contiguous SFRs and both little- and big-endian SFRs and SFR32, thanks Maarten!). But it does so at a cost: the 2 or 4 byte addresses are more difficult to get right. They introduce a fair amount of entropy which is not needed in most cases (most SFR should be little-endian, with strictly ascending SFR addresses). Taking the c8051f120 as an example, this f.e. boils down to "__sfr32 __at (0x93) MAC0ACC;" being easier to check for humans than "__sfr32 __at (0x96959493) MAC0ACC;". If a macro would be needed to convert SDCC's long SFR16/32 addresses to another compiler which should just support ascending little-endian SFR or otherwise bail out this would get lengthy. Maybe we can prepare one Header file (with sfr16/sfr32) for maximum portability (that is with macros for SDCC / Hi-Tech / IAR / Keil / Raisonance / Tasking /...) before release? ---------------------------------------------------------------------- Comment By: Maarten Brock (maartenbrock) Date: 2006-05-09 21:04 Message: Logged In: YES user_id=888171 Frieder, Maybe I'm stupid, but I still don't understand how this will help. A typical "other compiler" header file looks like this: sfr16 TMR2 = 0xcc; // Timer2 counter How are you going to convert that to: __sfr16 __at(0xcc) TMR2; If you use a script (like keil2sdcc.pl), the script can solve this. If you use macros (like atmel does), the macro can solve this. Btw. I've sent Atmel a message today about faulty macros in their header distribution. And I've sent TI a message about an outdated app.note. Maarten ---------------------------------------------------------------------- Comment By: Frieder Ferlemann (frief) Date: 2006-05-04 15:13 Message: Logged In: YES user_id=589052 The macro would help for the header conversion *from* other compilers. You'd have to setup another one for the conversion *to* other compilers. I was hoping for a line like this for the SFR16 address setup within SDCC: address=(address&0xff00)?address:((address+1)<<8)|address; ---------------------------------------------------------------------- Comment By: Maarten Brock (maartenbrock) Date: 2006-05-04 14:02 Message: Logged In: YES user_id=888171 May I suggest a macro to do the substitution. #define SFR16(name, addr) __sfr16 __at(((addr+1)<<8) | addr) name; It's not like you can share SDCC notation with other compilers anyway. Maarten ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=350599&aid=1481734&group_id=599 |