3

can someone help with this?

In summary: declaring and initialising a variable does not work in PIC hardware – whereas it works fine in simulation. Also, this problem seems to be worse if the variable is a structure. I am using: MPLAB X IDE V3.55, XC8 V1.41, PIC18F26K40 on Explorer 8 board with PICKIT3 debugger cable.

Details:

For a simple case like:

uint8_t myvar = 0x55;

void main(void)
{
    uint8_t var = myvar;
}

Using the variables window in the debugger myvar is always zero when I run this in hardware. But if I run the same code in the simulator it is all OK!

I have:

  • broken the problem down to simplest form that reproduces the problem
  • Tried disabling compiler optimisation - which does not fix this

Checking the values in the ‘File Registers’ debugger window. I can see no 0x55 when run in hardware – but it’s there in the simulator (at address 0x21).

It does work in hardware if:

  • myvar is declared and initialised as a const
  • myvar is declared and initialised locally (inside main)

Now if I use a struct type instead of a simple uint8_t like:

typedef struct {
    uint8_t a;
    char b[8];
}MYSTRUCT;

MYSTRUCT ms = { 0x55, "HELLO" };

void main(void)
{
    uint8_t var = ms.a;
}

The ms variable is initialised properly in simulation, but not in hardware. This time it does not initialise if the variable is declared in main or as a global. Again, declaring as a const does work. So there seems to be inconsistency here:

                                                uint8_t     struct type
global variable declaration and initialisation      N       N
global const  declaration and initialisation        Y       Y
local variable declaration and initialisation       Y       N

After debugging and stepping through with the assembler (.as) file it looks like myVar is trying to be initialised, but for some reason just doesn't in hardware. See below the relevant lines from the .as file. the address and value at key stages is shown as captured from the debugger during simulation. You can see at the end '__pdataCOMRAM' (the pointer into ram for myVar) is assigned 0x55. If I step through this in the hardware all steps are identical, but when we get to the end '__pdataCOMRAM' doesn't have the value of 0x55, but 0x00.

                                                    Address Value

global __pdataCOMRAM
__pdataCOMRAM:
  file  "main.c"
  line  32
global  _myVar
  myVar:                                            0x21    0x00
   ds      1        
    file    "dist/C18_18F87K22/debug\initTest.X.debug.as"       
    line    #       
psect   cinit       
; Initialize objects allocated to COMRAM (1 bytes)      
  global __pidataCOMRAM                             0x144   0xff55
  ; load TBLPTR registers with __pidataCOMRAM
  movlw low (__pidataCOMRAM)        
  movwf tblptrl     
  movlw high(__pidataCOMRAM)        
  movwf tblptrh     
  movlw low highword(__pidataCOMRAM)        
  movwf tblptru     
  tblrd*+ ;fetch initializer        
  movff tablat, __pdataCOMRAM+0                    0x21     0x55

Am I doing something dumb here or is there a compiler option I’m missing or is it a compiler or debugger bug? I would like to understand this problem so I don’t fall into any pitfalls further along in my development.

Cheers, Steve

StevedB
  • 51
  • 4
  • You should look at your linker script, I suppose. As far as I can understand the startup code does not perform a copy from flash `.data` section to ram to init global variable. It seems that all global variables are considered as `.bss` section, so zeroed at startup. Did you tried to declare as static `uint8_t myvar = 0x55`? – LPs Apr 10 '17 at 13:29
  • This is a very common error in microcontroller programming in general. I don't know this particular tool chain, but probably you have created a project with "minimal start-up" or "fast start-up" or similar. Create a new project and see if there is some option called "standard start-up", "ANSI start-up" or something like that. – Lundin Apr 10 '17 at 13:50
  • An optimizing compiler can drop the entire `uint8_t var = myvar;` assignment of `var` as `var` is never used. Do _something_ with `var`, something visible without using the debugger. – chux - Reinstate Monica Apr 10 '17 at 13:56
  • I've tried all combinations of 'Clear bss' and 'initialize data' linker options but they have no effect on this issue. I am writing in C so don't think I should have create memory initialisation files. I can see myVar get initialised with 0x55 in the .as and lst file. Indeed the (program) memory location identified here does have 0x55 in it - but it is not in ram, moving onto understanding the startup process :) – StevedB Apr 10 '17 at 14:36
  • Looking at the generated assembly code and stepping through the myVar is trying to be initialised, but doesn't for some reason - see update in question. – StevedB Apr 10 '17 at 16:50
  • It seems fairly obvious that your `.data` section isn't behaving. There's no inconsistency - as per some initialization requirements in the standard, structs might get placed in `.data` if you don't initialize all of the struct. Which you don't do here, you don't initialize the whole 8 byte array, just the first 6 bytes of it. (Possibly the struct will get moved elsewhere if you initialize it to `{ 0x55, "HELLO!!" };`). Either the start-up code isn't working or your `.data` RAM segment is incorrectly mapped. Did you try to make a new project? – Lundin Apr 11 '17 at 06:42

1 Answers1

2

It would appear there is a known silicon issue stopping access to program memory immediately after a reset. There is an ERRATA macro 'NVMREG' as a get around. Specific steps to solve were: Set project option 'Conf'>'XC8 global options'>'XC8 linker' select 'Additional options' category, then add NVMREG to Errata option. Then it all worked OK. Credit to 1and0 on the microchip forum for that one!

StevedB
  • 51
  • 4