We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hello,
I am developing an 8051 system / chip where I want to put the multiplication/division routines in a ROM. The real program should then call these routines instead of adding the library to the code.
For UART I exchange/override the getchar/putchar library routines with own ones. Is such an approach also possible for the multiplication routines?
The fallback method would be to define all possible multiplications/divisions as functions. And replace all * / with rom function calls. This increases the call overhead and I would write the code in a special style. This is what I want to avoid.
Thanks and BR, Joachim
With "real program" I mean a code located in XRAM.
BR
You forgot one of the most important parts of your question: why you want to accomplish by having your own multiply/divide functions. What exact issues do you have with the results you get natively from the compiler/linker?
With the ARM stuff we used to ROM a bunch of critical 32-bit routines, it was either single cycle or TCM, but run much faster than the FLASH. Also had some floating point libraries in there. Passed the routine addresses to the linker via a .DEF definition file.
It is quite common to have the linker move specially critical routines moved into RAM. But there are always issues with internal helper functions in the CRTL - if they are stored in flash but linked to be moved into RAM and are then called before having been moved then bad things happens.
When there are a time-critical algorithm, then the norm is to treat at least the full inner loop as critial and not just look at a multiply or divide unless we are talking of a large-number implementation.
I have an external flash for code execution. The performance is faster when executing the code from ROM instead of flash. That's the reason why I want to call functions located in ROM like mul/div/etc.. I have two separated images (uvision projects) - one for flash and one for ROM. Booting is done from ROM and if the flash is valid I start execution from flash. My Idea was to put the base multiplication library in the ROM. These routines are then called from by the flash image routines. So I do not want to write my own mul/div routines. I just want to execute the mul/div routines faster.
I have seen that the overhead for functions is not that much, when using the optimizer. So it should be ok to use special mul/div functions in the code to speed up inner calculations.
Nevertheless I have seen a much more critical point I have to solve (Maybe I should start a new discussion here ...).
I have looked in detail at the assembler code generated by c51. I have seen that it stores the function parameters somewhere in registers in IRAM. Due to the fact that there are two images the compiler/linker does not know which data locations are used. I expected that the functions are generated so that all used registers are saved (e.g. on "hardware" stack) and restored when leafing the routine again. This does not seem to be the case. So temporary variables are used somewhere in IRAM.
Is there any way to solve this issue? Some parameter/option? (I have already played with reentrant and NOREGPARAM. They do not seem the help here.)
Is there a better way of generating the code with keil? So that c51 knows about the ROM routines. Create a sort of library that is not linked together with the code but called "dynamically". Or something similar.
I have forgot a question: Can be sure that library routines do not modify IRAM data? Or at least operate non-desctructiv?
BR, Joachim
you need to compile the two together and locate as you need. Then split the .hex to load
Erik
Thanks,
I have already thought about this. But faced the problem, how do I make sure that the code does not change on the next compile. The ROM contents is fixed and cannot be changed anymore.
The above issue is a reason why time-critical routines are often copied to RAM - then every build may redefine the memory mapping. But the linker will insert code that will copy a freshly compiled function from flash to RAM for every new project build.
When instead having function code that is not recompiled, then you will always have a huge number of issues with more or less documented dependancies.
I have already thought about this. But faced the problem, how do I make sure that the code does not change on the next compile.
what do you care, just load both every time
Depends - if ROM really is ROM then there might not be a second chance :p
ROM is really ROM :( And I do not have enough RAM (area issues) where I could load the program to :(
Maybe I could include the assembler code of the ROM every time I compile the Flash contents? So that the compiler/linker is aware of the already used memory locations by the ROM.
In this case it would be good to reduce the available size of idata for ROM code to a small range. Is there an automatic way to achieve this? Some setting, pragma, ...?
But how little RAM do you have - note that there are options to just run individual functions in RAM. The linker can set up the binary so that the C runtime library will copy the code implementation for specific functions into RAM at the same time as it initializes global variables.
This is regularly used when an ISR or maybe a DSP inner loop is extremely time-critical - RAM normally represents the fastest memory region available.
Just that not all processors can run code from RAM. And some processors might have lots of RAM but only some of it able to run code - it's a question of caching and interaction with the pipeline.
That's a good idea. At least for multiplication this should be possible.
Nevertheless I already got it to run in a different way. I utilized a union located at a fixed position and size (reserved in both program parts) containing structs for each function in ROM for parameter passing and the functions should only use R0-R7 (checked manually in assembly code - maybe there is an automatic way?). The only critical thing is if R0-R7 hold variables in the calling program part that are overwritten (Compiler does not know which registers are modified). Until now I could not see a problem, but maybe somebody has here a better experience with that. If this does not work the solution would be to switch the register bank and reserve this bank iram locations as fixed global variables in the flash image.
Many thanks for your help and suggestions. BR, Joachim