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.
I need to be able to hold two applications on-chip at a time so I can choose which one to run (using a code based reset giving a start vector)
T89C51AC2
The default one will be compiled for the 'standard' memory location (0x0000?), and the second one, that will be flashed into memory via IAP at 0x4000.
My initial thoughts to compile a hex file for this upper location (in uVision 3) would be to change the project settings:
C51 Tab : (checked) Interrupt Vectors At Address: 0x4000 BL51 Locate Tab : (Un-Checked) Use Memory Layout from Target Dialog BL51 Locate Tab : Code 0x4000
This 'seems' to produce a hex file located at 0x4000 (although I am not yet ready to test its operation)
However, this hex file contains a line that writes to memory location 0x0000. Is this normal? This would overwrite data placed there by the lower memory hex file?!
Or, am I approaching this the wrong way, because something doesn't feel right here.
However, this hex file contains a line that writes to memory location 0x0000. Is this normal?
It would be reasonable, since the compiler thinks that code execution starts at 0x0000 in any case. If you look at this line closely, you should find that it contains a jump to the actual entry point of the program.
I didn't find a way in the MCUs datasheet to change the address of the interrupt vector, but maybe I didn't look closely enough.
So the three bytes at 0x0000 aren't actually part of the programs code, but an indicator to the processor for the start point.
So if I had multiple applications loaded into different parts of memory, I could just write three bytes to flash (at 0x0000) and perform a processor reset and the new code would run?
In which case, when I use IAP to program the upper areas of memory, I presume I can safely ignore (not write) the bytes for 0x0000, as long as I remember them as the entrance point for when I want to run the code at that part of memory?
Well, yes and no. They are actual code - a LJMP instruction to the appropriate address.
Under certain conditions. The interrupt vector table (IVT) seems to be fixed at 0x0000 for this processor, so all of your programs will still use the same table (the option to generate the IVT at a different address concerns the compiler only. The compiler has no idea if this makes sense or not - it does not if the processor has no way of changing the base address of the IVT).
Yes. Remember that the address is contained in the last two of the three bytes (refer to the format of the LJMP instruction). Also, remember the IVT issues. The solution for them might be not to use interrupts at all, or some clever way of dealing with the fixed IVT address in software.
Also, remember the IVT issues. The solution for them might be not to use interrupts at all, or some clever way of dealing with the fixed IVT address in software.
My code has two interrupts needed. One for timing, the other for 485.
Are you saying that I can't, without some major code re-writing, have two seperate areas of code that can run independantly of each other?
Basically then, there is just one jump table, which includes the Start Vector, along with the Jumps for interrupts. So, to be able to run code in different areas correctly, I'd need to alter all of these values?
No. Not without jumping through some hoops.
Yes. The fixed interrupt vector table address is one of the properties of the '51 architecture. There may be some derivatives out there that allow relocation of the IVT, but most do not.
What you could do is
* Use no interrupts in one of the two programs. I have a setup like this running - the second part is a bootloader which does not need any interrupts
* Have a flag in memory that indicates whether program A or program B is currently running, and put conditional jumps in the IVT that just jump to another jump table inside the appropriate program (which, of course, needs to be located at a fixed address if you don't want to update the IVT all the time). This adds a little bit of additional latency to the interrupts.
* Overwrite the IVT every time the program changes. Depending on how often this happens and how quickly the switch needs to take place, this probably isn't a very good solution.
I wouldn't need to change between the different applications that often at all. Once every few months maybe.
So, I guess it is possible that I can go the route of over-writing the IVT each time.
I've had a look around but I cannot find a specific memory map that shows me where things are supposed to be located. I've analysed a hex file configured to run from 0x4000, and apart from the boot vector (0x0000), the hex file doesn't contain any other information outside of the expected memory range (0x4000 - 0x6500). However, the code runs fine at that location (when programmed via flip as the only application in memory)
If the IVT was stored somewhere else, wouldn't it show up in the Hex file?
I'm sorry if I sound a little naive here. This is my first time looking at IAP and multiple applications, so my knowledge is pretty thin, and I can't seem to find anything that relevant in all the documentation that i've found.
Also, does it make any difference that I'm coding it in C rather than assembler?
Of course, the first decision must fit into the 8 byte space that is reserved for each interrupt vector.
Two LJMPs (3 bytes each) and a JB (3 bytes) won't work, but the 8 bytes can hold an JB, an AJMP and a LJMP. Or, if you want something more sophisticated, two PUSHs, a MOV direct, #immediate, and a RET (not necessarily in this order :) ), so you can actuall determine the address of the second jump table at run-time.
It should be at the address you specified in the Target/C51 dialog. There's nothing that's immediately obious about it, though - it merely contains a jump to the actual interrupt service routine.
Unfortunately, it does. The C compiler does not allow you to put any real code in the 8 byte space reserved for each interrupt vector - it only puts a jump to the actual ISR in there. If you want direct access to those 8 bytes, you will have to write the table in assembly.