Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   Programming (http://www.chiefdelphi.com/forums/forumdisplay.php?f=51)
-   -   EEPROM Code (http://www.chiefdelphi.com/forums/showthread.php?t=39973)

Matt Krass 12-10-2005 23:28

Re: EEPROM Code
 
It risks getting caught in an infinite loop waiting for the queue and breaks the comm sync on the controller?

sciguy125 12-10-2005 23:29

Re: EEPROM Code
 
Quote:

Originally Posted by Kevin Watson
Ugh, I just realized this code will cause the red-light-of-death. Anyone care to venture a guess as to why it won't work? I'll post corrected code tomorrow-ish.

-Kevin

I'm not sure, but I don't like that while

Code:

// wait, if necessary, for a free slot on the circular queue
while(EEPROM_Queue_Free_Space() == 0);

Won't that keep looping until the queue is full (which it never will be if it never leaves that loop)?

CJO 12-10-2005 23:31

Re: EEPROM Code
 
Quote:

Originally Posted by Matt Krass
It risks getting caught in an infinite loop waiting for the queue and breaks the comm sync on the controller?

Which is the ultimate result of what I mentioned (put more nicely).

Mike Bortfeldt 13-10-2005 09:52

Re: EEPROM Code
 
Kevin,

I haven't tried this, but from the PIC documentation, it looks like you only have to disable the interrupts during the period that you call "pre-write sequence" and "execute the write" in the EEPROM_Write_Handler routine. You should be able to re-enable the interrupts after these 3 lines (from the 39609b Microchip document, section 7.4) rather than waiting until the 2ms write is complete. This may also eliminate the code error by allowing the high priority interrupts to mostly go on schedule.

Mike

Kevin Watson 13-10-2005 13:38

Re: EEPROM Code
 
Quote:

Originally Posted by sciguy125
I'm not sure, but I don't like that while

Code:

// wait, if necessary, for a free slot on the circular queue
while(EEPROM_Queue_Free_Space() == 0);

Won't that keep looping until the queue is full (which it never will be if it never leaves that loop)?

Yep, it's the while loop. I'm trying to write ninety-one bytes, but the queue only has sixteen slots. The code sits in the for loop and eventually EEPROM_Queue_Free_Space() returns zero forever because EEPROM_Write_Handler() isn't getting called to do the actual EEPROM write. The only way the code would work is if he queue size were changed to ninety-one slots. The trig table code seems like something that teams could use, so I'm writing a version that'll generate sin()/cos() and tan() tables in EEPROM. I'll also write the code to do the table lookup.

-Kevin

Kevin Watson 13-10-2005 14:25

Re: EEPROM Code
 
Quote:

Originally Posted by Mike Bortfeldt
Kevin,

I haven't tried this, but from the PIC documentation, it looks like you only have to disable the interrupts during the period that you call "pre-write sequence" and "execute the write" in the EEPROM_Write_Handler routine. You should be able to re-enable the interrupts after these 3 lines (from the 39609b Microchip document, section 7.4) rather than waiting until the 2ms write is complete.

Thanks for the suggestion. I'd heard from another source that interrupts had to be disabled for the entire period to ensure a reliable write. As I wasn't sure what the answer was, I decided to err on the conservative side and disable interrupts globally for the entire period (at least on the first revision). When I get some time to work on it, I'll talk with the folks at Microchip to see what they say.

Quote:

Originally Posted by Mike Bortfeldt
This may also eliminate the code error by allowing the high priority interrupts to mostly go on schedule.

That isn't a problem because the high-priority interrupt never gets disabled (i.e., EEPROM_Write_Handler() never gets called). The problem is that getdata() and putdata() won't be called once the code gets stuck in the while() loop, which makes the master processor cranky. BTW, if EEPROM_Write Handler() gets called from Process_Data_From_Master_uP(), disabling the high-priority interrupt isn't a problem because it won't fire-off again until the next SPI packet arrives from the master processor in a period of time much greater than two milliseconds.

-Kevin

CJO 13-10-2005 16:46

Re: EEPROM Code
 
On a slightly different topic, does the addressing go from 0 to 1023 or 1 to 1024?

i.e. can I write to 0?

Kevin Watson 13-10-2005 16:51

Re: EEPROM Code
 
Quote:

Originally Posted by CJO
On a slightly different topic, does the addressing go from 0 to 1023 or 1 to 1024?

i.e. can I write to 0?

The range is 0 to 1023. I guess I should add that bit of information to the read me file.

-Kevin

CJO 13-10-2005 16:59

Re: EEPROM Code
 
Thanks, this makes it perfect for recording tables

If you want (say) a table with the five attributes in each row
0, 5, 10, . . . = attribute a
1, 6, 11, . . . = attribute b
2, 7, 12, . . . = attribute c
3, 8, 13, . . . = attribute d
4, 9, 14, . . . = attribute e

Then to find a specific row number, you would take the row number, multiply by 5 and subtract five, and then start reading values?

Dave Flowerday 13-10-2005 19:29

Re: EEPROM Code
 
Quote:

Originally Posted by CJO
On a slightly different topic, does the addressing go from 0 to 1023 or 1 to 1024?

i.e. can I write to 0?

As a rule of thumb, software people always count starting with 0. ;)

CJO 13-10-2005 21:46

Re: EEPROM Code
 
I have met one or two systems which did not, and not having a controller with me at the moment to test it out, I figured I might as well ask.

Kevin Watson 14-10-2005 02:18

Re: EEPROM Code
 
I just wrote and tested some quick-n-dirty trig table code. Grab a copy of the EEPROM code here and add the code below. I only create a table covering zero to ninety degrees because sin(x) in the other three quadrants can be derived using sin(x) data in quadrant one (exercise left to the student). I'll release a more polished version at a later time.

This code creates the table:

Code:


#include <math.h>
#include "printf_lib.h"
#include "eeprom.h"
/*******************************************************************************
*
* FUNCTION: Sine_Table()
*
* PURPOSE: Creates a sine table in EEPROM
*
* CALLED FROM:
*
* PARAMETERS: Unsigned int containing the address.
*
* RETURNS: 1 when finished creating table, 0 otherwise
*
* COMMENTS:
*
*******************************************************************************/
unsigned char Sine_Table(unsigned int address)
{
static unsigned char angle = 0;
static unsigned char done_flag = 0;
static unsigned char sine;
if(EEPROM_Queue_Free_Space() > 0 && done_flag == 0)
{
// calculate normalized sine value
sine = (unsigned char)255.0 * sin((float)angle * 3.14159265 / 180.0);
// write the angle and sine value to EEPROM
EEPROM_Write(address + angle, sine);
// send diagnostic information to the terminal
printf("writing x=%u sin(x)=%u\r", (unsigned int)angle, (unsigned int)sine);
// are we done?
if(angle == 90)
{
done_flag = 1;
printf("Finished!\r\n");
}
else
{
angle++;
}
}
return(done_flag);
}

This code verifies that EEPROM was written correctly:

Code:


/*******************************************************************************
*
* FUNCTION: Verify_Sine_Table()
*
* PURPOSE: Creates a sine table in EEPROM
*
* CALLED FROM:
*
* PARAMETERS: Unsigned int containing the address.
*
* RETURNS: 1 when finished creating table, 0 otherwise
*
* COMMENTS:
*
*******************************************************************************/
unsigned char Verify_Sine_Table(unsigned int address)
{
static unsigned char angle = 0;
static unsigned char done_flag = 0;
if(done_flag == 0)
{
if(EEPROM_Read(address+angle) == (unsigned char)(255.0 * sin((float)angle * 3.14159265 / 180.0)))
{
printf("angle=%u verified\r", (unsigned int)angle);
}
else
{
printf("angle=%u failed\r\n", (unsigned int)angle);
}
if(angle == 90)
{
done_flag = 1;
printf("Finished!\r");
}
else
{
angle++;
}
}
return(done_flag);
}

This code goes into Process_Data_From_Master_uP():

Code:

if(Sine_Table(0) == 1)
{
Verify_Sine_Table(0);
}
EEPROM_Write_Handler();

-Kevin

kc8nod 09-11-2005 14:11

Re: EEPROM Code
 
Quote:

Originally Posted by Kevin Watson
The range is 0 to 1023. I guess I should add that bit of information to the read me file.

-Kevin

Hi Kevin,

I've got a question about EEPROM_Write().

Code:

unsigned char EEPROM_Write(unsigned int address, unsigned char data)
{
        unsigned char return_value;

        // return error flag if the queue is full
        if(eeprom_queue_full == FALSE)
        {
                // put the byte and its address on their respective circular queues
                eeprom_queue_data[eeprom_queue_write_index] = data;
                eeprom_queue_address[eeprom_queue_write_index] = address;
       
                // increment the queue byte count
                eeprom_queue_count++;

The parameter address is an unsigned integer, but eeprom_queue_address is an array of unsigned chars. Aren't you chopping off two bits from the address? Or did you mean to define eeprom_queue_address as an unsigned int also?

Kevin Watson 09-11-2005 15:09

Re: EEPROM Code
 
Quote:

Originally Posted by kc8nod
Hi Kevin,

I've got a question about EEPROM_Write().

Code:

unsigned char EEPROM_Write(unsigned int address, unsigned char data)
{
        unsigned char return_value;
 
        // return error flag if the queue is full
        if(eeprom_queue_full == FALSE)
        {
                // put the byte and its address on their respective circular queues
                eeprom_queue_data[eeprom_queue_write_index] = data;
                eeprom_queue_address[eeprom_queue_write_index] = address;
 
                // increment the queue byte count
                eeprom_queue_count++;

The parameter address is an unsigned integer, but eeprom_queue_address is an array of unsigned chars. Aren't you chopping off two bits from the address? Or did you mean to define eeprom_queue_address as an unsigned int also?

Ugh, It may be a bug, but I won't have time to look at it until this evening.

-Kevin

Kevin Watson 09-11-2005 18:36

Re: EEPROM Code
 
Quote:

Originally Posted by kc8nod
Hi Kevin,

I've got a question about EEPROM_Write().

Code:

unsigned char EEPROM_Write(unsigned int address, unsigned char data)
{
        unsigned char return_value;
 
        // return error flag if the queue is full
        if(eeprom_queue_full == FALSE)
        {
                // put the byte and its address on their respective circular queues
                eeprom_queue_data[eeprom_queue_write_index] = data;
                eeprom_queue_address[eeprom_queue_write_index] = address;
 
                // increment the queue byte count
                eeprom_queue_count++;

The parameter address is an unsigned integer, but eeprom_queue_address is an array of unsigned chars. Aren't you chopping off two bits from the address? Or did you mean to define eeprom_queue_address as an unsigned int also?

Yep, it certainly looks like a bug, an old bug. I'm not sure what happened, but the latest code isn't on the website. I'd added a EEPROM_Wipe( ) function and incorporated the change Mike Bortfeldt suggested (above), but for some reason the code never got uploaded. I guess I'll have to up the dosage on my brain fart medication <grin>. Thanks for catching this.

-Kevin


All times are GMT -5. The time now is 00:13.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi