Hello I am working with a C161U micro on an EASY UTAH target. Well I have two projects, startup and application, that I load on Flash with the Flash Tool. At the target reset, what it is on flash begins to run: the startup project. The startup project copies the application project from flash to RAM, and its last instruction is to jump to the beginning of the RAM, and then the application project is executed from RAM. To accomplish this, I must avoid absolute call to functions by converting the calls in relative calls thanks to the key word near before each function. For example the function void near config (void) is at address 0x20100 (this is the load address in Flash), so if the RAM start address is 0x110000, then this function is copied at address 0x110100. When this function is called, this is not with a CALLS CC_US, 0x20100 but with a CALLA CC_US, 0x00100 thanks to near. The call is then relative and the function is executed from RAM. Well, I have a problem with the library functions used in my program C_PCASTS or MEMCPY, because they are executed in Flash. I don't know how to specify that they must be called with relative calls since I can't put the near word before their declarations. How to obtain their execution in RAM and not in Flash? Thanks for your help Best regards Carmen
All functions are near in small memory model, unless specified otherwise. All library functions are near in small memory model, I think. But to get your program to run from RAM you don't have to worry about that. Build your main application with proper memory layout, that is, to execute from RAM (0x110000-...). To program it to flash (0x20000-...), you will have to generate Intel HEX file with all addresses shifted down (-0xF0000), uVision has that option. That HEX file will be suitable for burning the flash. At startup, you can copy your main application from 0x20000-... to 0x110000-... and run it from there without worrying about addresses. - Mike
Hello, Thanks Mike for your response. I use the large memory model. This is for that I need to specify that all functions are near when executing. Yes, this is what I do. I generate two HEX files (one for startup project and one for application project). The startup project copies the application project from flash 0x20000 to RAM 0x110000. But I observe that for doing a multiplication, for example, the call to the library function is CALLS ?C_FPMUL(0x20204) and not CALLA ?C_FPMUL(0x00204) as I expect (this is what happened for functions declared with near). The first command implies that execution is really done at address 0x20204, that is to say in Flash, and the second command implies that the execution is done at a relative address of 0x204 starting from the RAM base address, that is to say from 0x110000, that is to say at the address 0x110204, where the FPMUL library function is copied. I know how to have relative calls for functions I defined and wrote on my program, but not for library functions already defined. Do someone know how to do this? Thanks for help. Regards
Hello Carmen, the call to the library function is CALLS ?C_FPMUL(0x20204) and not CALLA ?C_FPMUL(0x00204) as I expect (this is what happened for functions declared with near) In large memory model all library functions are far and they are called with the CALLS instruction. From your observation I can also see that code address range for your application was specified to be in flash: ROM: start 0x20000, size 0x20000 RAM: start 0x110000, size 0x20000 (or something like that in the target options) If you want your code to reside in your board's RAM, however, your memory ranges have to look like that: ROM: start 0x110000, size 0x10000 RAM: start 0x120000, size 0x10000 (I don't know the sizes, so correct that) because during build all the code goes to the 'ROM' range. But the 'ROM' range doesn't have to be in physical ROM, it can be your board's RAM just as well. So after you've changed your target options, you'll see that all calls to library functions will look like this: CALLS ?C_FPMUL(0x110204) // or whatever Of course, the HEX file will start at 0x110000, so it's not suitable for burning into flash directly. But it's a minor problem, you can solve it easily (see my previous message). - Mike
See Keil App note #138. It describes linker commands which allow the program code to be located at one address (Flash) and run at another address (RAM). Best Luck Scott
Hello, Thanks for your response. I don't think that application note 138 applies exactly to what I need to do with the library. About the memory ranges: as I have two different projects that will be executed together in the target, it is not possible to declare memory ranges on both. So the startup project has ROM 0x0000 to 0x80000 (size of the flash), and RAM 0x110000 with a size of 0x40000. This project contains also an .a66 file for initialization. The application project have no specification about memory ranges, it includes the file .a66 but with the option "Link Publics only". What I do is to use the directive RENAMECLASS combined with some definitions in "User Classes" to could have the code at address 0x20000. This is necessary to could load this project on the block 2 of the flash. If for example I use the real RAM address 0x110000, then it is impossible for me to load the flash. So what I need is to modify the way in which the library functions are called, that is to say to modify CALL from far to near without changing the memory model. Thanks a lot for valuable help I received Regards Carmen
About the memory ranges: as I have two different projects that will be executed together in the target, it is not possible to declare memory ranges on both. I believe that is not true. Consider other options. Regards, - Mike
hello, I do not understand what you mean, but I check that if I put on the project application the same memory ranges than in the startup project, then when I execute on target nothing function! I remind that for executing from RAM a program loaded on flash, I need two different programs, one the startup which permits to copy the application from flash to RAM and its last intruction is to jump to the first one in RAM. The other program is the application. It is loaded on flash too. When the startup jumps to the first instruction in RAM (it is the first instruction of the application program) the execution is right until it arrives to the use of a library function, then the program goes back to flash to execute the library function, and what I want is that this execution of this library function goes on RAM.
My idea is: For your startup application let the memory ranges be ROM: start 0x20000, size 0x1000 RAM: start 0x110000, size 0x800 And for the main application ROM: start 0x110800, size 0x10000 RAM: start 0x120800, size 0x10000 This way the ranges for the two applications do not overlap, so they won't conflict with each other. Presumably, the startup application needs very little memory, so the rest can be used for the main application. That's it. I can't see a problem with that. Regards, - Mike
Another solution might be to make a local C implementation of the memcpy function that expects exactly the pointer types as they appear in your flash programming code. In this way you can avoid the CALLS instructions.
One of the startup functions I use does the following: 1) Checks the main program in Flash using a CRC. 2) Copies the program to external RAM. 3) Copies a small code segment to XRAM. 4) Jumps to the start of the XRAM code. 5) The XRAM function remaps the RAM to 0x00'0000 where flash used to be. This function was written in assembly and is about 15 lines long. 6) Performs a pseudo reset by resetting the stack pointer and jumping to 0x00'0000. 7) The application then performs it's own 'startup.a66' and runs. This function also handles download and programming of flash if the program is corrupted. You must be careful of the EINIT instruction since it locks the SYSCON register, stopping remapping of the internal flash to 0x01'0000. One of my other startup functions leaves the internal flash alone since it is the fastest code memory but copies external flash to external RAM to avoid the wait state. This code must be able to ID the processor since internal flash sizes vary from processor to processor. Best Luck Scott