CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

dspic rtsp and getenv confusion..

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
gareth_trinity



Joined: 27 Feb 2017
Posts: 6

View user's profile Send private message

dspic rtsp and getenv confusion..
PostPosted: Mon Feb 27, 2017 2:30 pm     Reply with quote

Hello all.
I am trying to write a rtsp code for my application.
MCU is dspic33ev32gm004.

Several topics on here refer to the bootloader example but that is not what I am trying to implement and reading that code it feels like “I can’t see the wood for the trees”,

I want a small amount of reserved space in flash (at end of flash) for the rtsp code that contains a custom serial protocol driver.

The main code will be put into “reflash mode” where it will jump to this rtsp code and allow the master controller to write flash.

I am getting hopelessly confused with the numbers I am seeing from the getenv() functions wrt to the datasheets.

Data sheet says each instruction is 3 bytes or 4 bytes if you count the phantom. These are arranged as two 16 bit words.

A row is 64 instructions or 192 bytes or 256 bytes if you count the phantom.

An erase block is 8 rows or 512 instructions or 1536 bytes (or 2048 bytes if you count the phantom).

Addressing of flash is on increments of 2 because tblwl and tblwh gives access to the words, so addressing should be as simple as 0, 2, 4, 6, 8, 10..
This all seems very easy.
But I cannot tally that with the information from the ccs compiler v5.070 and the docs are not too clear.

BYTES_PER_ADDRESS gives 2 but should this be 3 or 4 if you count the phantom?
BITS_PER_INSTRUCTION gives 24. But why not 16 given the value of BYTES_PER_ADDRESS. And why not 32 if it’s counting the phantom?
FLASH_WRITE_SIZE is giving 8 as the minimum write size – I have no idea why – should this be 4? Why 8 bytes?
Because write_program_memory() says that it requires a multiple of 4 bytes and the 4th should be 0 as it is ignored – so it is counting the phantom byte afterall?
Certainly looking at the hex and binary compiled outputs for my program the compiler is generating 32 bits per instruction and the top byte is 0 (phantom).
So why is BYTES_PER_ADDRESS not 4? And BITS_PER_INSTRUCTION not 32?
FLASH_ERASE_SIZE is giving 2048! This would be correct if it was considering the phantom byte (64 per row * 8 rows * 4 bytes per row) but it’s not stacking up with BITS_PER_INSTRUCTION and BYTES_PER ADDRESS.

One difficulty is in knowing how to use these to identify flash erase boundaries.
Because when arranging my code ORG sections I need to ensure that the rtsp code starts on an erase block boundary so it doesn’t get a part of it accidentally erased.

But with erase sizes of 2048 this clearly doesn’t stack up against the real datasheet block sizes of 1536.

ORG says it works in terms of program words, so is this the same as per datasheet of 0, 2, 4, 6, 8… Or is it conforming to the compiler BYTES_PER_ADDRESS and so would need to be 0, 4, 8…

Finally I have no understanding of the addressing that write_program_memory() is expected to take?
Data buffer is a multiple of 4 bytes, count must be a multiple of 4.
Does the address start at 0 and increment in 2’s for each instruction? Or 4’s?
Is this correct:
Code:

Unsigned int8 insn1[4] = {blah, blah, blah, phantom};   // one instruction
Unsigned int8 insn2[4] = {blah, blah, blah, phantom};   // one instruction
Write_program_memory(0, insn1, 4);
Write_program_memory(2, insn2, 4);

Or should it be:
Code:

Write_program_memory(0, insn1, 4);
Write_program_memory(4, insn2, 4);

Nothing in the docs explains this at all.

Reading the asm output for Write_program_memory() is getting me nowhere.

Any help would be really appreciated.
Gareth
jeremiah



Joined: 20 Jul 2010
Posts: 1339

View user's profile Send private message

PostPosted: Mon Feb 27, 2017 3:02 pm     Reply with quote

I can't access the data sheet from here, but some comments:

1. There are two bytes per address in PIC24 and dsPIC chips. Each address represents a word (16 bits, two bytes).

2. BITS_PER_INSTRUCTION is 24. It is a 24 bit instruction chip. Yes there is a phantom byte in memory, but this particular constant doesn't describe the physical layout of memory, just the size of the instruction. It is not meant for doing address calculations.

3. I can't check this chip, but most of the other ones cannot write a single byte at a time, but can write a row at a time (some chips can write a byte at a time, but not most). A row can be whatever it needs to be. On the PIC24FJ it is 256 bytes long. That PIC could very well have an 8 byte write available. it will be in the register options.

4. Again, can't check the data sheet, but the 2048 flash erase size looks legit (and a common value you see). It does include the phantom bytes.
gareth_trinity



Joined: 27 Feb 2017
Posts: 6

View user's profile Send private message

PostPosted: Mon Feb 27, 2017 3:25 pm     Reply with quote

Thanks for the reply.
Maybe I am over thinking all of this, but I feel very unsure with the numbers.
If I take the 2048 erase size at face value - and trust that every 2048 it will erase the page automatically, e.g.
write_program_memory(0, data, 2048);
write_program_memory(2048, data, 2048);
...

This is much simpler and I don't have to worry about the datasheet saying every 1536 bytes..

What do I use for ORG values?
these are in terms of program words according to the manual, or are they in terms of addresses given to write_program_memory()?
According to the datasheet there are 512 instructions (program words?) per erase block:

E.g. are they
#ORG 0, 2047 DEFAULT
// code here will be in the first erase block

#ORG 2048, 4095 DEFAULT
// code here will be in the second erase block

or, if in terms of program words:
#ORG 0, 511 DEFAULT
// code here will be in the first erase block

#ORG 512, 1023 DEFAULT
// code here will be in the second erase block
Ttelmah



Joined: 11 Mar 2010
Posts: 19451

View user's profile Send private message

PostPosted: Mon Feb 27, 2017 3:48 pm     Reply with quote

Yes.

You have to distinguish bytes from words, instructions, and the 'byte counts' involved in data transfers.
All physical memory addresses are including the phantom bytes. They have to. Everything works using these, you just can't actually do anything with the fourth byte. So it's always 2048 'byte counts'.
The instruction is 24bits. If you wanted to use the memory to hold something, it has 24bits available. Would be misleading to say it had 16 or 32. Hence BITS_PER_INSTRUCTION = 24.
The word size is 2 bytes. BYTES_PER_ADDRESS
Write_program_memory accepts an array of bytes to write. So 2048 bytes, with every 4th one not used.
FLASH_ERASE_SIZE is in 'byte counts'.
jeremiah



Joined: 20 Jul 2010
Posts: 1339

View user's profile Send private message

PostPosted: Mon Feb 27, 2017 5:06 pm     Reply with quote

One thing to watch out for with the #org (and I think write_program_memory) is that those addresses are "word" addresses and not byte addresses (so 2048 bytes => 1024 words). so you should be using things like:

#org 0, 1023 default

though I prefer
#org 0x0000,0x03ff default

as that maps better with memory map diagrams.

If you are still unsure, I would suggest doing something the following type of program:

Code:

//ensure no code goes here
#org 0x0400,0x07ff {}

void main(void){
   unsigned int8 a1[] = {1,2,3,0,4,5,6,0};
   unsigned int8 a2[] = {7,8,9,0,10,11,12,0};
   unsigned int8 b[sizeof(a1) + sizeof(a2)];

   //see if word addresses work
   write_program_memory(0x400,a1,sizeof(a1));
   write_program_memory(0x404,a2,sizeof(a2));
   read_program_memory(0x400,b,sizeof(b));

   /** Now Print the results of b[] **/

}


You'll find that if you use 0x408 in the second write call that you will get a bunch of 0xFF in the last half of b[].
gareth_trinity



Joined: 27 Feb 2017
Posts: 6

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 5:21 am     Reply with quote

Thanks for your replies, it has helped a lot.

One more question though.
If FLASH_ERASE_SIZE is 2048 bytes, 1024 words and 512 instructions - all of this now makes sense and correlates to the datasheet.

Why does:
get_env("PROGRAM_MEMORY");
return #5580 (21888)

This env says "Returns the size of memory for code (in words)"

I would have expected it to be a multiple of FLASH_ERASE_SIZE in words, i.e. a multiple of 1024?

It's tricky because if you want to position your boot loader at the end of flash then you have to handle a weird partial size?
gareth_trinity



Joined: 27 Feb 2017
Posts: 6

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 8:09 am     Reply with quote

OKay so i think I understand where it is getting the 0x5580 for PROGRAM_MEMORY from.
The datasheet states that user instructions are from 0x200 to 0x577f so this difference is 0x5580.

But 0 to 0x1ff is the goto, reset and the IVT which are areas that must be programmed during rtsp.

So PROGRAM_MEMORY is not giving a true representation of the available space to be programmed.

I am not sure I can use the getenv() variables to truly create a s/w that can do reflash.

Will have to hard code in some constants to match the chip rather than have it adapt to whatever chip I an programming for.
jeremiah



Joined: 20 Jul 2010
Posts: 1339

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 8:35 am     Reply with quote

gareth_trinity wrote:
OKay so i think I understand where it is getting the 0x5580 for PROGRAM_MEMORY from.
The datasheet states that user instructions are from 0x200 to 0x577f so this difference is 0x5580.

But 0 to 0x1ff is the goto, reset and the IVT which are areas that must be programmed during rtsp.

So PROGRAM_MEMORY is not giving a true representation of the available space to be programmed.

I am not sure I can use the getenv() variables to truly create a s/w that can do reflash.

Will have to hard code in some constants to match the chip rather than have it adapt to whatever chip I an programming for.


That looks like a bug for that chip. PROGRAM_MEMORY should be telling you the location of the FUSES, which is 0x5780. I checked all my other chips, and it works correctly for them.

I would recommend sending CCS support an email and show them the bug. If you need a different chip to compare to, the PIC24FJ64GA104 correctly shows the FUSES address for PROGRAM_MEMORY.

Side note: As you probably noticed, the 0x5780 is not a page boundary. That means the FUSES are stored on the last page. The implications of this are you should not erase the page they reside on unless you plan to rewrite the fuse bits yourself. If I do a bootloader, I tend to leverage this page for some of my bootloader code since I won't be reflashing it anyways (I do a weird combo of upper and lower sections for my bootloaders).
gareth_trinity



Joined: 27 Feb 2017
Posts: 6

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 10:51 am     Reply with quote

Thanks, this confirms what I was thinking.

The application will operate in either run or reflash mode.
An eeprom location will record which mode it should start in.
Only when the master is happy that it has written the image it wants to will it change from reflash to run etc.
When in run mode it can also rewrite the boot loader.
So I will have to ensure that the boot loader is on its own set of pages that can be erased - so staying well away from the config bits which I don't intend to allow to be erased.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group