I'm trying to set up code to preload the EEPROM of a PIC16F628A with the necessary data depending on the value of one #define
, so the uC is ready to be popped into a PCB and be used without any extra procedure.
This is what I did so far:
__eeprom uint8_t A_RESET[2] = {0x00};
__eeprom uint8_t B_RESET[REMOTEMEM*3] = {0xAE};
__eeprom uint8_t C_RESET[128 - (sizeof A_RESET) - (sizeof B_RESET)] = {0xFF};
In this exapmle, I'll use a REMOTEMEM
of 4, so this should be the EEPROM map:
ADDRESS | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0A | 0B | 0C | 0D | 0E | 0F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
00 | 00 | 00 | AE | AE | AE | AE | AE | AE | AE | AE | AE | AE | AE | AE | FF | FF |
10 | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF |
20 | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF |
30 | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF |
40 | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF |
50 | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF |
60 | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF |
70 | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF | FF |
But instead, MPLAB ends up doing this:
ADDRESS | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0A | 0B | 0C | 0D | 0E | 0F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
00 | FF | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
10 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
20 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
30 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
40 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
50 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
60 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
70 | 00 | 00 | AE | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
I have previosuly used to have only one variable type __eeprom
, and I had to write all 128 locations of the EEPROM on that variable. I want to avoid that because now I have that REMOTEMEM
that can be changed.
1 Answer 1
I do agree that at its core the question is one about programming language syntax. It does seem more appropriate to ask this specific question in this forum as the members here are more aware of what the poster is trying to implement in an embedded controller.
That said this is how I did it: enter image description here
/*
* File: main.c
* Author: dan1138
* Target: PIC16F628A
*
* Created on August 1, 2023, 11:34 AM
*
* See: https://electronics.stackexchange.com/questions/675769/how-can-i-dynamically-preload-the-eeprom-on-a-pic-microcontroller/676147#676147
*/
// PIC16F628A Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#define REMOTEMEM 4
__eeprom struct {
uint8_t A[2];
uint8_t B[REMOTEMEM][3];
uint8_t C[128-(2+REMOTEMEM*3)];
} EEmem = {.A[0 ... 1]=0x00,
.B[0 ... REMOTEMEM-1][0 ... 2]=0xAE,
.C[0 ... 128-(2+REMOTEMEM*3)-1]=0xFF
};
void main(void)
{
volatile static uint8_t Index, CheckSum;
for(;;)
{
CheckSum = 0;
for(Index = 0; Index < 128; Index++)
{
CheckSum += ((__eeprom uint8_t *)(&EEmem))[Index];
}
}
}
-
\$\begingroup\$ Why do you use volatile and static on the local variables in the main function? \$\endgroup\$Oskar Skog– Oskar Skog2023年08月02日 07:28:51 +00:00Commented Aug 2, 2023 at 7:28
-
\$\begingroup\$ @OskarSkog, Because the XC8 optimizer is aggressive I use the volatile storage class to trick the compiler into generating code for the main loop. \$\endgroup\$Dan1138– Dan11382023年08月02日 19:32:53 +00:00Commented Aug 2, 2023 at 19:32
__eeprom
keyword, so I can't comment on that part, but in standard C, initializing an array with a single value, for example your__eeprom uint8_t B_RESET[REMOTEMEM*3] = {0xAE};
does not initialize the entire array with that value - it only initializes the 1st element of the array. The only exception to that is if you initialize with0
, so your__eeprom uint8_t A_RESET[2] = {0x00};
is valid. \$\endgroup\${[a ... b] = c}
function in C and it actually works with XC8. Now all the spaces of the array are initialized with the values I want, but they're organized backwards. First, all the0xFF
s, then the0xAE
s and at the end the0x00
s. Do you know any standard way of changing the order of variable creation in memory? Since the EEPROM is not mapped in the memory of the uC, I cannot use__at()
to fix the arrays in memory. \$\endgroup\$__eeprom struct {uint8_t A_RESET[2]; uint8_t B_RESET[REMOTEMEM*3]; uint8_t C_RESET[128 - (sizeof A_RESET) - (sizeof B_RESET)]; } = { {... initializer for A_RESET}, {... initializer for B_RESET}, {... initializer for C_RESET} };
\$\endgroup\$