Hi, I'm back with more questions :)
I have a 4-element array of 4-byte bit field structures filling up my bit addressable memory. Those structures are manipulated a lot in my code. I have found that assigning a pointer to an array element and then working with it generates much less code than working with the element directly. In one piece of my code, I want to do a logical operation with a lot of 2-bit structure fields. A line that does that looks like this:
pointerToStruct->2bitField ^= pointerToStruct->2bitField << 1;
This is compiled into a lot of instructions, but the beginning looks like this:
MOV R0, 0x01 PUSH MOV A, @R0 MOV R4, A
My program breaks at the last instruction with error 65: access violation at I:0xE7: no 'read' permission. When I look at my registers, R0 really contains 0xE7. The first instruction should have put 0x01 in R0. PUSH should not have affected it as far as I know. If I check &pointerToStruct in the watch windows, the address is really D:0x01, so this should be ok.
Any ideas about how 0xE7 ended up in my 0xE7? Is it possible that my stack overflows? If it tried to go beyond 0x7F, would it wrap around and start writing into register banks or what?
Would it possibly make a difference if you write:
MOV R0,#0x01
instead of
MOV R0,0x01
Heh, I can't choose what to write, I write C and it's compiled into instructions. Anyway, you make a good point, this is actually direct memory addressing, not immediate as I first thought.
Isn't 0x01 memory bank 0? The function is question has no memory bank specified, but it is called from a function which uses memory bank 1. Should the final function be using bank 0 or 1?
Finally, any ideas how my pointer ended up in the memory banks? I'm using small memory model. Is it possible that I ran out of space for data in the internal memory? I thought the compiler might at least warn me or start using pdata or something.
MOV R0,0x01 is the equivalent of mov R0,R1
the only difference MOV R0,0x01 = mov R0,<R1,register bank 0> mov R0,R1 = mov R0,<R1,current register bank> thus if the current register bank is 0 there is no difference
Erik
Yeah, I figured that out.
Also figured out that default bank is 0, regardless of what the calling function used.
Also figured out that my pointer is in a register because it's a local and C51 is storing it there normally.
Just can't figure out why it is pointing outside the 128 bytes of directly-addressable internal memory. Anyone know what C51 does with SMALL memory model when it runs out of directly-addressable memory for variables?
Ok, I think I've tracked down the potential problem. My pointer is bad because the parameters passed to the function are wrong. My function takes 5 parameters, all in 0-3 interval. The call
func(0, 0, 2, 3, 1);
is compiled to:
MOV 0x4C, #0x03 MOV 0x4D, #0x01 MOV R3, #0x02 CLR A MOV R5, A MOV R7, A LCALL func
Obviously, the call is try to pass some of the parameters through registers. However, when the program enters the function, the registers no longer contain the intended data because the caller was using different register bank. The called function fetches a parameter from R7, for example, but it contains 0x3f instead of 0.
Is there any way to fix this? Can I give the compiler some directives that will make it aware that it can't use register banks like that?
you are doing the no-no of calling a function both from main() and an ISR
The function I'm calling from both main and timer interrupt is not a problem. That one works correctly. It's for the initial mode of my 8051 and it will be called forever until the program is set into some other mode, which is when my problems start. I removed the function call in main, but it only changes the place where my other function tries to access something that is out of bounds.
My chain of calls is timer_isr (using 1) --> oneOfFourFunctionsInATable (using2) -> oneOfTwoFunctions (using 3)
oneOfTwoFunctions is the one that is receiving bad parameters through registers. Is this kind of set up a no-no as well?
Is this kind of set up a no-no as well?
That's actually even worse. It's the same no-no, except you cause it fully explicitly instead of letting the compiler break this on its own.
are you aware that functions can not call functions with a different 'using' if you are, the compiler should give a warning NEVER ignore warnings
Thanks for help. I wasn't aware of it. None of the sources mention it. Also, I got no warnings from the compiler at all. I'll remove the 'usings' and hope I don't overflow the stack.