PDA

View Full Version : EEPROM Issue



mpgmike
- 1st July 2018, 22:07
First, the set up: I’m using a PIC18F25K50 with HIDmaker for USB communications with a PC. I use Virtual Studio 2015, Visual Basic for the PC side programming. The PIC is part of a controller, while the PC software is a tuning “dashboard” of sorts. The idea is to have Programmable Parameters that can be tuned by the user with the PC. These Programmable Parameters are then stored in the EEPROM of the PIC (at least that’s the goal).


The USB part of things appears to be working just fine. In fact, the HIDmaker software has made that part of the design rather reliable. I pre-load values into the EEPROM addresses with PBP3 “DATA @add,val” commands. When I start the Dashboard for the first time after a “burn”, all of the data is as it should be, 25 times out of 25. As long as I don’t try to “Save Changes”, the values will come up the same every time.


However, if I change ANY value (there are over 200) and Save Changes, EVERYTHING goes wonky. After 5 days of frustration, I isolated a single variable to work with. It NEVER came back the same as I programmed it (from the PC side). Here is a brief of what I’ve tried:



When “Save Changes” command received by the PIC, GOSUB BurnToEeProm for all Programmable Parameters. This would be the most logical and simplistic approach. Values were corrupted.
Created a PC screen to monitor raw data before the VB software turns it into something meaningful to a tuner (human). This was to help spot when and where the variables got corrupted. Definitely on the PIC side.
Created a second set of variables; Var & OldVar. If Var <> OldVar Then : WRITE new value. It was hoped this would reduce latency.
Used “DEFINE WRITE_INT 1”, it dropped the USB every time I tried to Save Changes. This is a PBP3 command that disables Interrupts (GIE) while Writing to the EEPROM, then re-enables them when done.
Created a rotation variable Erot so that only one EEPROM WRITE was executed for each loop in the Main program. This was to prevent dropping the USB. USB still dropped out until I eliminated “DEFINE WRITE_INT 1”.
Increased the USB polling interval from every 10 ms to 50 ms.
Read through the PIC Data Sheet, created an ASM subroutine to burn to EEPROM using the exact syntax from the Data Sheet using the EECON1, EECON2, EEADD, and EEDATA Registers, got the same results.
Executed an EEPROM Save subroutine using PBP3 that mimicked the Data Sheet ASM sequence, same results.
Used both PBP3 & ASM subroutines with GOSUB and @ CALL, mostly the same results.
Placed the “long save” code (Data sheet style) in the regular subroutine (no GOSUB, no WRITE command).
Reviewed the software, both PIC & PC, numerous times to verify proper processing of the data. (I did find many bugs which I fixed, but haven’t been able to spot any lately.)
Reformatted parts of the software, both PIC & PC, to try to accomplish the same thing, but with a different approach (the PIC side is roughly outlined above and below).
Pulled my hair out & drank a screwdriver.
Lost sleep.


Here are a few things I have been able to confirm:

The EEPROMs are functional. Using “DATA @add,val” works every time.
The READ command is working, I get the same values every time.
The USB is working, I get the same values every time for fixed test values
The Save Changes command is sending the Program Counter (PC) to the proper subroutine (GOSUB SaveChanges works).
The value sent from the PC by USB is corrupted in the WRITE sequence on the PIC side.
The values written to the EEPROM are always wrong, usually have a pattern, but often the pattern is different from one time to the next.


Example 1:
Variable is CB, stored in EEPROM address 132. The value sent from the PC is 150d. Usually (but not always) the value returned is 148d.


Example 2:
A Byte array called Ramp[4]. Ramp starts at EEPROM address 128 (128 >> 131). Values sent from the PC are: 40,30,20,10. A few examples of the values returned are:


146,22,151,23
138,10,139,11
142,18,147,19


If there was consistency in the values returned, it might help me to isolate the issue & correct it. I’m at a total loss. I’ve been at this for several days (dozens of hours). Any help would be more appreciated than you could possibly know. Shown below are a couple renditions of the code used for saving to EEPROM:




FOR b0 = 0 TO 63
IF OldFX[b0] <> FX[b0] THEN ;Tried both “<>” and “!=“ variations
WRITE b0, FX[b0]
OldFX[b0] = FX[b0]
ENDIF
NEXT b0
; More variables in between
FOR b0 = 128 TO 131
b1 = b0 - 128
WRITE b0, Ramp[b1]
NEXT b0





IF Erot = 132 THEN ;Erot is my EEPROM Save Rotation variable
IF OldCB != CB THEN
WRITE 132, CB
Erot = Erot + 1 ;Move to the next variable on the next rotation
OldCB = CB
ENDIF
ENDIF





EEADR = 132
EEDATA = CB
GOSUB Write_EE
DO
LOOP UNTIL EECON1.1 = 0 ;EE_WR, Software Set, HardwareCleared Write Command
EECON1.2 = 0 ;EE_WREN


Write_EE:
ASM
BANKSEL EECON1
BCF EECON1,EEPGD
BCF EECON1,CFGS
BSF EECON1,WREN
BCF INTCON,7
MOVLW 0x55
MOVWF EECON2
MOVLW 0xAA
MOVWF EECON2
BSF EECON1,WR
BSF INTCON,7
ENDASM
RETURN

HenrikOlsson
- 2nd July 2018, 06:50
Now there's a problem description if I've ever seen one :-)

My bet is that it has something to do with the interrupts. Have you tried to disable the USB comms and change/save/read back the EEPROM values in some other way just to verify that the routine that does the EEPROM writing is actually working properly. Not that I see why it shouldn't but it'll give you further clues and/or verification that it IS the USB comms/interrupts that's the culprit.

I'm surprised that your approach with the rotation variable didn't work. I was going to suggest to put the "write to EEPROM routine (one byte at the time)" in the USB Service routine but if your main routine doesn't run slower than the USB service interval your approach would basically do the same thing. The manual says that the WRITE command is self timed and "may" take up to 10ms, have you measured how long it actually takes?

How long does your main code take to exectute? Can you, as a test, disable interrupts al togheter and just call the USB service routine once each pass?

/Henrik.

richard
- 2nd July 2018, 10:25
one more thought, do any of your isr routines alter the eecon registers , ie a read eprom

mpgmike
- 2nd July 2018, 17:50
Thanks for the thoughts. I tried something, in the subroutine to SaveChanges I used WRITE 132,150 instead of WRITE 132,CB. The retrieved value was 150. It's not an EEPROM issue after all. Somehow my variables are getting corrupted somewhere. I'm reviewing all code with a "magnifying glass in one hand and a fine tooth comb in the other" to try to find where things are going awry. Thanks all.

Ioannis
- 2nd July 2018, 19:47
write 132,CB is not correct. You have to write 132,$CB.

Ioannis

mpgmike
- 3rd July 2018, 01:12
No, CB is the name of my variable, not the value.

HenrikOlsson
- 3rd July 2018, 05:51
Do you have (or can you add) a debug port (EUSART, SEROUT, DEBUG)?
If so, then print the value of your variable out before calling the write routine, before executing the write command, after executing the write command, read the value back immediately after and print it out again.

Is CB declared as a BYTE?

If you're indexing arrays somewhere then doublecheck that you're not writing outside the range of the array.

mpgmike
- 3rd July 2018, 08:31
CB is declared as a BYTE. I checked the arrays' indexing several times. I have a spread sheet with all the variables listed, size (BIT, BYTE, etc), USB ID#, the internal code used to communicate each variable with other PICs on the board (there are a total of 6), and some other criteria. I've been working on this project for the past several years. It's due in less than 2 weeks.

I decided to rebuild the HIDmaker side of things. I found several variables, including arrays, that were structured as signed bytes. I'm dealing with the sign in software and forgot I did that earlier. I will be totally revamping it around the proper non-signed bytes and try again.

Ioannis
- 3rd July 2018, 08:38
This makes me wondering, how can one follow every detail in a large program.

Too many variables and chances are something will go wrong.

Ioannis

richard
- 3rd July 2018, 08:41
much easier in C
local vars and scope make life easier , user defined structures remove all doubt

Ioannis
- 3rd July 2018, 08:54
Local vars is a dream (and in wish list) for PBP.

I think with a bit of creativity, structures can be implemented with arrays in PBP also.

Not specific to data structures though.

Ioannis

richard
- 3rd July 2018, 09:39
pbp structures , not really
I tried this for array of mixed variable types [ effortless in C ] but its more trouble than its worth

http://www.picbasic.co.uk/forum/showthread.php?t=21068&highlight=structure

mpgmike
- 5th July 2018, 17:39
I'm restructuring the whole USB protocol. I think I figured out I was trying to shove a 247 byte packet through a 64 byte USB hole. Instead of creating a new USB ID# for every variable I need to transfer (247 of them), I will build a 64 byte packet with relevant data. This will most definitely speed up the transmissions as well as offer the flexibility of not having to transfer a bunch of data that hasn't changed.

Each variable will have a unique code (0x00 >> 0xFF) that gets loaded into iCmd(x) (at the PIC side) or oCmd(x) (at the PC side) with the data value being put into iData(x)/oData(x). For a 64 byte array, it takes 2 packets; Table1L and Table1H. On the PC side I added a module to handle sorting and loading packets. Hope to be back testing later today.

And to think I originally thought this was an EEPROM issue. I'm on a learning spree once again.

mpgmike
- 8th July 2018, 19:24
After 2+ weeks of battling this challenge, I have conquered!

Issue #1: Trying to shove 247 bytes of data through a 64 byte Endpoint.
Fix: Restructured the Send/Receive from lots of variables to a 64 byte packet. The packet can be structured any way I need.

Issue #2: The HIDmaker-generated code for Sending Reports had a glitch.
Fix: I found it & fixed it in my code. I notified Dr. Bob about the glitch, hopefully it will be incorporated into his current releases and any updates he issues. I'm madly in love with HIDmaker, but it isn't quite perfect.