From: SourceForge.net <no...@so...> - 2006-05-11 18:19:03
|
Feature Requests item #1481734, was opened at 2006-05-04 12:14 Message generated for change (Comment added) made by maartenbrock 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: Open Priority: 5 Submitted By: Frieder Ferlemann (frief) Assigned to: Nobody/Anonymous (nobody) 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: 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 |