This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Self Programming a cc2530 bootloader

Other Parts Discussed in Thread: CC2530

Well Hello to everybody. I am a new user on the forum, and now I have been studying the cc2530 for almost 3 months, making my own board, from the schematic to the firmware, I think I have some useful and pertinent questions to increase our knowledge about the controller and tools.

I found some questioning about this discussion, but the post is from the last year so I decided to make a new.

http://e2e.ti.com/support/wireless_connectivity/f/156/p/58886/916187.aspx#916187

The controller I am using is the cc2530F256 and my IDE is IAR for 80518.30.1.41636 

So I will point some of my decisions and open them for discussion, in the middle I will put some doubts I have.

-> Decided to do bootloader on my own. No External Tools, from 0. 

->CPU Core: Plain, Code Model: Near, Data Model Large, XDATA stack reentrant ( I did that because some of the DMA flash access routines didn´t work out without that model )

->Default values for stack/ heap, data pointer, and all the rest.

So the main point of a bootloader is the ISR. All the rest is what we do best and I don't think its necessary to bring on the topic. I decided to throw away all the C directives and do all inline assembler. So I organized the interrupt vector using the ORG directive and above 0x100H I put the ISR itself.

My boot code starts at 0x0000 and ends at 0x3EFF. I left the 3F00 to 3FFF an open safe area between the boot code and main code. That will be explained in a few.

The 8051 before enters the native interrupt vector address, it puts into the stack the return address H:L, only.

->That is what I need to know where my code is running.

->If an interrupt comes and de high ADDR is above 40, The main application is running. If its below 40 the bootcode is running.

->Thats the reason I left the 3F empty. Since I make a subtraction and use de JC instruction, it saves me a JZ instruction in case I tested against 0x40. So now I test against 0x3F and I know there is nothing between 3F and 40 high address.

-> Since 8051 has no indexed access to the stack, and it does not save Acc, PSW, and to operate with DPH and DPL I need to restore them using some XCH instruction against registers, I realy need to use those registers. So I decided to use the bank 3 (zero based).

->After I save Acc, PSW, DPH, DPL, I change the bank, pop the ADDR (H) of the stack into Acc, make the SUBB operation and use the JC instrucion.

->If main code is running I load DPTR with the ADDR(H) and ADDR(L) of the realocated interrupt vector of the main code ( I choose all the same addr, with plus 0x4000 (0x4003, 0x400B..)). And push it into the stack. After I restore DPTR, PSW, Acc and use the RET instruction. 

-> If bootloader code is running I simply call the boot external ISR routine using Lcall and in code its simply declared as __interrupt void.

-> I tested the bootloader running and its working great. I use a banked main code and generate the intel HEX and modify the record address of the __program_start using notepad to be written to 0x4000 and use the Smart RF erase, append and verify the code. It really uses bank areas because I opened the raw-binary file and it has written code above 0xFFFF.

->After appending, I open my IDE with the bootloader and debug it into the chip, but the linker pattern "fill unused code mem" is not set. Otherwise it wouldn't work.

some considerations:

-> In linker file of the main code, I change the pattern -D_NEAR_CODE_START=0x0000 to -D_NEAR_CODE_START=0x4000. 

So now I have some doubts:

-> First question I have: ? Is PSW, Acc and DPTR the only context I need to return ? 

-> When I first tested, after the jump to main code the processor stalled. Looking into the debugger I could realize that in DATA memory space, after a instruction with XSP(L), it was inserting values into the space of the register bank 3. So my question is:

? Why is the compiler using that space if by default  in linker I tell it that :

-D?REGISTER_BANK=0x0 
-D_REGISTER_BANK_START=0x0

So the default register bank addr is 0. Why does it use that third register space, and another question is that it doesn't  even change RS0 or RS1 to access the register_bank=3 space ?

When I changed 

-D_REGISTER_BANK_START=0x0 to -D_REGISTER_BANK_START=0x8 

the thing started to run. I could realize that also the space of the register bank 0  that before the change was barely used, started to be often used (and that is what I want because those registers are flip-flops of low power)

But the expected to that change would be that the bank0 would remain untouched. isnt´t it?

How exactly does those directives of register bank on linker work?

The solve to all of my troubles I used the #pragma register_bank=3 before all the declared interrupts on main code.

That made the compiler stop alocating that third bank to do operations. 

Well I hope we can start a discussion from here. That is really my first post and I'm sorry if there is lack of info in somehow or the things are not clear.

Thanks