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

problem with arrays in structs V4.129

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



Joined: 07 Feb 2009
Posts: 40

View user's profile Send private message

problem with arrays in structs V4.129
PostPosted: Thu Feb 23, 2012 5:22 pm     Reply with quote

Compiler V4.129

Working example program below. I've tried to keep this very simple - the code is taken from a very large program but only enough is shown here to describe my problem.

Probably faster to start reading at the bottom of the main function before trawling through the eeprom writing or reading stuff.

Code:
#include <18F6722.h>

// DEFINES ==========================================================
#define TRISC                              0b10111011
#define SCL0_PIN                        PIN_C3
#define SDA0_PIN                        PIN_C4
#define WP_EEPROM                        PIN_C5
#define EEPROM_ADDR                     0xA0
#define TEST_LOCATION_LENGTH      21
#define MAX_TESTS                        20
// END DEFINES ======================================================

// FUSES ============================================================
#FUSES NOWDT          //No Watch Dog Timer
#FUSES HS             //Crystal osc
#FUSES NOCPD          //No EE protection
#FUSES NOPROTECT      //Code not protected from reading
#FUSES MCLR           //Master Clear pin used for I/O
#FUSES PUT            //Power Up Timer
#FUSES NOBROWNOUT     //Reset when brownout detected - //check this
#FUSES NOLVP               //No Low voltage programming
// END FUSES ========================================================

// HELPERS ==========================================================
#device ICD=true
#device adc=10
#device PASS_STRINGS=IN_RAM
#use delay(clock=10000000)
#use i2c(stream=RTCC_MEM, MASTER, scl=SCL0_PIN, sda=SDA0_PIN, SLOW=100000)
// END HELPERS ======================================================

// TYPE DEFINES =====================================================
typedef unsigned int8 u8bit;
typedef unsigned int16 u16bit;

typedef struct
{
   u8bit                        checksum;
   char                        default_location[5];
   u8bit                        last_test_result;
}TESTS_INFO_STRUCT;
// END TYPE DEFINES =================================================

// GLOBALS ==========================================================
TESTS_INFO_STRUCT test_info;
// END GLOBALS ======================================================

//-------------------------------------------------------------------
void memory_write(u8bit base_address, u16bit address, u8bit * data, u16bit length)
//-------------------------------------------------------------------
{
   BOOLEAN nack;
   BOOLEAN boundary;
   u16bit start_address;

   start_address = address;

   while (length > 0)
   {
      boundary = FALSE; //we can start anywhere
      i2c_start(RTCC_MEM);
      i2c_write(RTCC_MEM, base_address);
      i2c_write(RTCC_MEM, make8(address, 1));
      i2c_write(RTCC_MEM, make8(address, 0));

      while ((length > 0) && (!boundary))
      {
         //check if we are crossing a 64 byte boundary
         boundary = (((start_address + 1) % 64) == 0);

         i2c_write(RTCC_MEM, *data);
         data++;
         length--;
         start_address++;
      }
      
      i2c_stop(RTCC_MEM);

      //We try addressing it and wait for it to acknowledge - we then know we can continue
      nack = TRUE;

      while (nack)
      {
         delay_ms(10);
         i2c_start(RTCC_MEM);
         nack = i2c_write(RTCC_MEM, base_address);
      }
   }
}

//-------------------------------------------------------------------
void memory_read(u8bit base_address, u16bit address, u8bit * data, u16bit length)
//-------------------------------------------------------------------
{
   i2c_start(RTCC_MEM);
   i2c_write(RTCC_MEM, base_address);
   i2c_write(RTCC_MEM, make8(address, 1));
   i2c_write(RTCC_MEM, make8(address, 0));
   i2c_start(RTCC_MEM);
   i2c_write(RTCC_MEM, base_address + 1);

   while (length > 0)
   {
      *data = i2c_read(RTCC_MEM, length > 1);
      data++;
      length--;
   }

   i2c_stop(RTCC_MEM);
}

//-------------------------------------------------------------------
void main(void)
//-------------------------------------------------------------------
{
   set_tris_c(TRISC);

   disable_interrupts(INT_RDA);
   disable_interrupts(INT_SSP);
   disable_interrupts(INT_EXT);
   output_high(WP_EEPROM);

   //initialise values in struct to 0
   memset(&test_info, 0, sizeof(TESTS_INFO_STRUCT));   

   //read the memory to see what has stuck during a power down
   memory_read(EEPROM_ADDR, 60, &test_info, sizeof(TESTS_INFO_STRUCT));

   //initialise values in struct to 0 again
   memset(&test_info, 0, sizeof(TESTS_INFO_STRUCT));

   //store the values in eeprom
   output_low(WP_EEPROM);
   memory_write(EEPROM_ADDR, 60, &test_info, sizeof(TESTS_INFO_STRUCT));
   output_high(WP_EEPROM);

   //initialise values in struct to something obviously wrong
   memset(&test_info, 0xA5, sizeof(TESTS_INFO_STRUCT));

   //read the memory to see if they have stuck this time...
   memory_read(EEPROM_ADDR, 60, &test_info, sizeof(TESTS_INFO_STRUCT));

   //ok, here we see the problem, the data that is now read out is as follows:
   //checksum = 0 as expected
   //default_location[5] = 5 x null as expected
   //last_test_result = 255 which is not as expected

   //arghh!
}

// ==================================================================


If I move the array to the last element of the struct then all works - at least for this specific example.

Quote:
typedef struct
{
u8bit checksum;
u8bit last_test_result;
char default_location[5];
}TESTS_INFO_STRUCT;


It looks to me like something odd is happening in the eeprom reading code once it encounters an array in the data structure.

After reading around the forum, I have tried the (int8 *) cast in case that helps but it doesn't.

Am I making any obvious errors??
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Fri Feb 24, 2012 12:30 am     Reply with quote

Why you're not telling the observed problem clearly instead of hiding it in the file comments?

If I understand right, you are saying that the last byte of the structure is read incorrectly (0xff instead of 0x00). You didn't perform a test that shows if it's a read or write problem.

P.S.: I see, that the problem is by design. The write function is stopping byte write purposeful after address 63, so it's only writing 4 of 7 bytes.
eskimobob



Joined: 07 Feb 2009
Posts: 40

View user's profile Send private message

PostPosted: Fri Feb 24, 2012 2:20 am     Reply with quote

Hi FvM,

Thanks for your reply

FvM wrote:
P.S.: I see, that the problem is by design. The write function is stopping byte write purposeful after address 63, so it's only writing 4 of 7 bytes.


It is supposed to ensure that I do not cross a 64 byte boundary without issuing an I2C_STOP and then starting again. It does continue to write after address 63 however now you have caused me to look at it more closely, I can see that I am not incrementing the address variable so that when it goes around the loop again to write bytes after a 64 byte boundary, it actually overwrites the earlier bytes again. I can actually get rid of start_address.

This now works:
Code:
     while ((length > 0) && (!boundary))
      {
         //check if we are crossing a 64 byte boundary
         boundary = (((address + 1) % 64) == 0);

         i2c_write(RTCC_MEM, *data);
         data++;
         length--;
         address++;
      }


Thanks for helping me to spot my mistake Very Happy
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