This works without a problem, except I have to look up the structure of the call every time I add one. Also the readability is not exactly great. a structure in upper 64 k of "code flash" in a SILabs f122typedef struct { U32 MSFC_tag; // 'MSFC' Multi-Size Font Collection // MSFC U32 MSFC_idno; // random unique font id number (referenced by subfonts if split) // fb06c05c U8 MSFC_ver; // file version (set to 1) // 01 U8 MSFC_tblcnt; // number of table dir entries following // 03 U8 MSFC_sftcnt; // number of subfonts contained in / belonging to this collection // 01 U8 MSFC_flags; // 0 for standard CBFs (bit0=1 for vertical font) // 01 U16 MSFC_fsiz; // Complete size of the file (max size is 65534 (= 0xfffe) bytes) // 061a } STR_MSFC; a function //////////////////////////////////////////////////////////// // // // FUNCTION U32 ReadFlashLong (U8 code * RFSaddr) // // read high flash // U32 ReadFlashLong (U8 code *RFSaddr) { U8 RFCintsav; U8 RFCdata; U8 code * RFSadds; U32 RFScomp; RFCintsav = SG_IE; SG_IE = 0; SG_SFRPAGE = 0; if (RFSaddr > 0x7fff) { SG_PSBANK = 0x30; } else { SG_PSBANK = 0x20; RFSaddr += 0x8000 ; } RFSadds = RFSaddr; for (RFCdata = 0 ; RFCdata < 4 ;RFCdata++, RFSadds++) { RFScomp <<= 8; RFScomp |= (U32) *RFSadds; } SG_IE = RFCintsav; return (RFScomp) ; } the call s_msfc = 0 ; if ( FFS_CfntNo == 2) { s_msfc = 0x8000 ; } FFSLtemp = ReadFlashLong ((U8 code *) &s_msfc->MSFC_tag); what would be "natural" FFSLtemp = ReadFlashLong (s_msfc->MSFC_tag) gives error; is there a simpler way to make the call without specifying a pointer to something now specified as a pointer (asx seen in bold above). I am NOT interested in a suggestion about using "banking" my other routines do not have the time to go through a bank check/switch. I am using a 100Mips '51 and can hardly keep up. Also, the shorts and longs are in the wrong order because the files with these structures are generated on a PC so, even using "banking" would not totally solve the problem. Erik
To reduce line length of some lines (I detest multiline statements) I am doing it this way which, while not "pretty" does work:
#define RFL ReadFlashLong ((U8 code *) & FFSLtemp = RFL s_msfc->MSFC_tag);
re void pointer: no way do i need the overhead, I will try the U32 version What makes you assume there'll be overhead? There'll be less visible clutter in the calls (because you no longer need that cast), and if there's runtime overhead involved at all, it'll become less, not more, since it's now restricted to a single occurence inside the called function, instead of happening at every call site. I use these structs together with a PC program that generate the file from which I work and thus a commonality is needed. If at all, that's actually an argument against copying the struct definition over to the C51 side. Because of alignment and endian-ness issues, C structs are generally unfit to define communication protocols. Given that you already need accessor functions to resolve the endian-ness, you might as well go all the way and do it all via accessors:
FFSLtemp = get_MSFC_tag(msfc);
None that you haven't categorically ruled out as part of asking the question. The most logical-looking construct would definitely involve xdata banking, no matter how much you dislike it. What you're doing in ReadFlashLong() is not very much different from xdata banking, either --- you might even find it to be more efficient.< 1) it is not xdata, it is code 2) when accessing this part, I have time, so efficiency is of no concern, the concern is when other parts, which require MAX speed, are running where banking will interfere with the speed. By not banking the slow, there is no banking overhead of the fast. Erik
"1) it is not xdata, it is code" Doesn't this chip give you the option to map (some of) the flash into XDATA space?
not that I know of, but then the datasheet is 350 pages. Anyhow it is irrelevant since I never write to it with this code. Erik actually to write to it you need this
//////////////////////////////////////////////////////////// // // // FUNCTION void WriteFlash (U8 xdata * WFSaddr, U8 WFCdata) // // read high flash // void WriteFlash (U8 xdata * WFSaddr, U8 WFCdata) { U8 WFCintsav; WFCintsav = SG_IE; SG_IE = 0; SG_SFRPAGE = 0x0f; SF_CCH0CN &= 0xfe; // single byte write SG_SFRPAGE = 0; if (WFSaddr > 0x7fff) { SG_PSBANK = 0x30; } else { SG_PSBANK = 0x20; WFSaddr += 0x8000 ; } S0_FLSCL |= 0x01 ; // flash write S0_PSCTL |= 0x01 ; // movx to flash *WFSaddr = WFCdata ; //write the byte S0_PSCTL &= 0xfe ; // restore S0_FLSCL &= 0xfe ; // restore SG_PSBANK = 0x10 ; SG_IE = WFCintsav; }
"it is irrelevant since I never write to it with this code." That's irrelevant! The point of XDATA banking in this context is that it maps constants (which would normally be in CODE) into XDATA space. That said, I don't know if it's actually of any use to you! Maybe a red herring?
it is not xdata, it is code Actually, in the context of xdata banking, it'd be neither. It'd be far const, i.e. a memory class separate from both the usual xdata and code. Don't let the name deceive you. Just because it's called 'xdata banking' doesn't mean it can only extend the usual 'xdata' space. Think of it as generic >64KB memory support. when other parts, which require MAX speed, are running where banking will interfere with the speed. I think you really should check back on what xdata banking actually does before you continue this campaign. There's absolutely no overhead involved in parts of the program that don't themselves use objects in far memory.
I think you really should check back on what xdata banking actually does before you continue this campaign. There's absolutely no overhead involved in parts of the program that don't themselves use objects in far memory. in this context, what is an "object" another issue is that I doubt that banking will include the needed code to read the f12x high code area. it is a lot more than setting an address bit Erik FYI, here is what is required
//////////////////////////////////////////////////////////// // // // FUNCTION U8 ReadFlashChar (U8 code * RFSaddr) // // read high flash // U8 ReadFlashChar (U8 code * RFSaddr) { U8 RFCintsav; U8 RFCdata; RFCintsav = SG_IE; SG_IE = 0; SG_SFRPAGE = 0; if (RFSaddr > 0x7fff) { SG_PSBANK = 0x30; } else { SG_PSBANK = 0x20; RFSaddr += 0x8000 ; } RFCdata = *RFSaddr; SG_PSBANK = 0x10 ; SG_IE = RFCintsav; return (RFCdata) ; }
in this context, what is an "object" "Object" is C standard terminology for "a variable or a function". In the given context, a variable. I.e. code that doesn't touch 'far' variables won't even notice that xdata banking exists, much less suffer any overhead from it. I doubt that banking will include the needed code to read the f12x high code area. Not automagically all by itself, of course. But xdata banking is exactly the way you can get the compiler to help you with this kind of work. Keil basically offers you the opportunity to teach the runtime library new tricks here, so you can use perfectly ordinary C operations to access variables in that memory space. It won't cover the endian-ness conversion, but it'll allow you to access that struct in the simplest and most obvious way imagineable:
some_var = msft.MSFT_field;