Von: Peter Bigot Gesendet am: 12 Aug 2010 03:04:29
> I'm not convinced that presence of a single far pointer requires that every > address kick up to 32 bits. If near/far is maintained as an attribute on > the symbol, as apparently IAR uses a __data20 qualifier, it should be > possible to manage things properly. Whether GCC+binutils makes it > reasonably easy to do this, I don't know yet, but it's certainly not a new > problem. Unfortunately it is necessary. As soon as a single register holds a 20 bit address, ALL functions in EVERY part of the application need to save 20bit registers instead of 16 bit. Including all ISRs. Imagine the pointer being held as a register variable in R11. You call a function that IS 20bit-aware, yet it does not use R11. But it calls a function that is not but does need R11 locally. So it pushes 16 bits of R11 to the stack and restores them later. And the original funciton will have its local far register pointer truncated to 16 bits. Things are even more difficult for the call if the pointer in question is a function pointer and not a variable pointer. At some point you'll need to assemble the address to the required 20 bit address pointer. If then a non-20 bit-aware ISR interferes, you're callign low-mem without noticing. The only way to circumvent this would be putting the address into a local variable on stack and calling the function with CALL x(SP). Quite a performance hit even if you pass the pinter as a 32 bit value in R14/R15. And it needs some 'smartness' from the compiler, as users won't expect to have to do such 'optimizations'. (if you can at all force the compiler to not use a register for a local variable or parameter at all). > If a function address is qualified as near/far, adapting the CALL > instruction to the right form at the time the executable is generated should > be straightforward. If a function is qualified near/far, the type of CALL needed is already set by this qualifyer. Far functions require a far call (and will do a far return), near function don't require a far call but if it is allowed to call them from within a far function they need a far return too and therefore need to be called with a far call too. So once you are using far code, all code needs to use RETA and CALLA. No place for any single RET or CALL instruction in this code anymore. Unfortunately the required code not only depends on the type of function called, but also how/from where it is called. So it's an ever or never. > Some email from Dmitry Diky to the binutils reflector > back in the mid 2000s when MSP430X was first added implied the linker (as > opposed to assembler) was already handling that sort of thing in some cases > where PCREL jump instructions were selected based on the size of intervening > instructions. Locating and updating the corresponding RET may be a bit > trickier, though again this isn't a problem that only applies to the MSP430. jump instructions are different, as they are relative and do not consist of a call/ret pair that has to match. > Maybe this isn't doable, but I think it's worth putting some serious effort > into trying. If putting printf format strings in far memory means doubling > the size of every address in my application, I'm not sure I'm going to want > to enable that "feature". Maybe it would be sufficient to provide a far version of printf that is optimized to handle this without 20 bit pointers and/or use assembly language with cleared GIE during the critical fetches. The Atmel does something similar for format strings in program code (as its harvard architecture separates data and program space with different access instructions). There's a printf and a printf_P. Only difference is the access to the format string. So there need to be two versions of printf which have a far or near format string. Alternatively, the format string parameter could be always 32 bit. It would slow down normal printf slightly but would be transparent. The compiler needs to check and warn. Also, an additional format qualifier is needed, so you can pass 32 bit pointers to string parameters. JMGross > > Von: Michiel Konstapel > Gesendet am: 10 Aug 2010 14:40:06 > > >> Generally using 20 bit registers isn't advisable as it increases code > >> size and execution times and only a fraction of the MSP users needs > >> the additional code size. Many (inlcuding me) just need the higher > >> speed, more ram or better peripherals. > > > On the other hand, many (including me) are mainly interested in the > > extra flash and are happy to take the step BACK in RAM going from a > > 1611 to a 2418. "It's faster" doesn't help if you're stuck at "but it > doesn't > > fit" :) > > Some do, some don't. Indeed, if you NEED the space, then you need it. > My experience at e2e.ti.com is that many only think they need it while > they actually need petter programming skills and more imagination :) > > >> And even if so, often putting the functions far is good enough. > > >Constant data, too, would be nice, but I agree with the advantages of > >sticking to 16 bit data pointers (unless 20 bits are requested by a > >switch). > > The problem is that it affects code. If you use a single 20 bit > pointer, then all code in the whole project needs to be written > to support 20 it pointers. As it needs to save the registers as 32 > bit on stack, (including ISRs), needs to deal with stack parameters > differently etc. > > > For bulk data, you can fall back to a manual loading routine. > > that's what I do with my dynamically loaded firmware update and for > some constants. A hand-crafted 'getter' and 'setter' method. > Those who are already using C++ objects won't notice the > difference or the overhead :) > > > Being able to automatically split code into both low and far memory > > would be great, but as far as I understand, is fairly impossible for ld. > > Yes, it's a rather complex task > > >>>*) How much unhappiness would there be if the default compiler behavior > was > >>> to support near-mode compilation, with far-mode for code and/or data as > >>> an option specified either by attributes in the source or compiler > flags? > > >I don't mind which becomes the default, if it's easy to (globally) > >change. The -mdata-64k and -mcode-64k flags of mspgcc3's MSP430X branch, > >or their inverse, would do the trick. > > But it is necessary to note the usage of these flags in the object file. > You may not mix code compiled with or without a flag. It will result in > erratric program behaviour. > > > >> So my proposal is: far attribute for functions and constants (automatic > >> for strings e.g. in printf), but for constants only if enabled with > >> additional commandline switch. > > > Then the command line switch would select a different, precompiled > > library with far data pointers? > > yes. > > > If I understand correctly, the overhead for 20 bit code addresses is > > localized to the functions that use it (so libraries can be compiled > > once and will work either near or far), but 20 bit data pointers force > > that overhead on the whole program? > > Basically yes. 20bit program code needs to be called with 20bit > CALLA instruction, but the calling function and all surroundings may > be 16 bit completely except for the function call itself. > ISRs work transparent (the missing 4 bits are automatically saved > in an unused area of the status word) > > A problem are all library functions which take (callback) function > pointers. As the pointers (and pointer variables) are 16 bit. > If these functions use a long value and deal with it properly, > things should work independently of the data model. > Main candidate is printf. > > Once 20 bit data pointers are used, almost all code needs > to take care of it. At least all ISRs and any > code that is called below the first point where these are > used. > > Imagine an ISR that clears the upper 4 bits of your library > functions local data, right in the middle of execution... > Hence the need of a 'data model compatibility flag' in the object file. > > Perhaps this can be emulated by using different code segments for > code using 16 or 20 bit data, and the linker script ensures that only > one of them is populated... > > JMGross >