Peter1
Peter1

Reputation: 97

Read SPI Eeprom using a pointer does not work but works when not using a pointer

I am new to programming and I am trying to read a page (64Bytes) from an SPI Eeprom and I got it working when reading to an array[67] (3 transmitted Bytes to start the read process via SPI + 64 Bytes data).

I am using IAR Workbench working on a STM32L475.

When I try to use pointers it does not work, probably a stupid no brainer of a beginners mistake, but I appreciate some help to solve this.

I am using a union like this (I know I am wasting mem but for the test it is like this):

//Production Data union
union Production_Data_union
  {
  struct 
    {
    uint8_t Dummy_Array[3];
    char Xxxx_Sn[16];
    char Yyyy_Sn[16];
    char Prod_Date[8];
    char Firmware_Ver[8];
    };
  uint8_t Eeprom_Page0_Buffer[67]; 
  };  

union Production_Data_union Prod_Data;

uint8_t *Eeprom_Page0_Ptr;

uint8_t Read_Cmd[3] = {0x03, 0x00, 0x00};
uint8_t Buff[67]; 
uint8_t Eeprom_Page_Size = 64;  

void Eeprom_Page_Read(uint8_t *Data, uint8_t Page_No);  

My Main looks like this:

Eeprom_Page0_Ptr = (uint8_t*)&Prod_Data.Eeprom_Page0_Buffer;
Eeprom_Page_Read(Eeprom_Page0_Ptr, 0);

The Eeprom_Page_Read function:

void Eeprom_Page_Read(uint8_t *Data, uint8_t Page_No)
{  
  uint16_t Address;
  Address = Page_No * Eeprom_Page_Size;
  Read_Cmd[2] = Address & 0xFF;
  Read_Cmd[1] = (Address >> 8) & 0xFF;
  //Send READ command to Eeprom

  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);

  if(HAL_SPI_TransmitReceive(&hspi3, (uint8_t*)Read_Cmd, (uint8_t *)&Data,     (Eeprom_Page_Size +3), 5000) != HAL_OK)
   {
            Error_Handler();
  }

  printf("Prod_Data:\n - Xxxx SN %s\n - Yyyy SN %s\n - Prod date %s - Firmware %s\n - Cmd - %d - %d -         %d\n", 
               Prod_Data.Xxxx_Sn, 
               Prod_Data.Yyyy_Sn, 
               Prod_Data.Prod_Date,
               Prod_Data.Firmware_Ver,
               Read_Cmd[0],
               Read_Cmd[1],
               Read_Cmd[2]);

//Wait for SPI transfer to complete
  while (HAL_SPI_GetState(&hspi3) != HAL_SPI_STATE_READY)
  {
  } 
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);

    Read_E2prom = 0;
  }

I know the content of the Eeprom is ok and I can read it if I replace “&Data” with “Buff” (Array[67]) in the HAL_SPI_TransmitReceive(...) call.

Pointer value is the start address of the structure (0x20000090). So addressing a.s.o. should be ok but the struct is empty when using a pointer.

I am mostly interested in why this does not work and a fix to this, not so much in comments like "why don't you do it like this instead, I want to learn what I have done wrong cause this approach, I believe, should work.

Please remember that I AM NEW at programming so please explain "for Dummies".

Upvotes: 0

Views: 249

Answers (2)

Hein Wessels
Hein Wessels

Reputation: 947

I am not sure why that is ?

The function HAL_SPI_TransmitReceive wants a pointer to know where to store the data it receives. It essentially wants an address of where to go place the bytes. In your case, according to line

void Eeprom_Page_Read(uint8_t *Data, uint8_t Page_No){...}

Data is already a pointer, because it's denoted with a *. This means that Datais a pointer pointing to some uint8_t number/array somewhere. That somewhere is where you want your SPI to write to.

When you added the & you basically gave the SPI the pointer to the pointer of where you want to write. So the SPI is writing the received data over the pointer, instead of at where the pointer points?

If that doesn't make sense then ask me again. It's a hard thing to explain.

Update:

This is as I understand it, not a pointer but an array?

The compiler only see's it as an pointer. In your case the pointer happen to point to an array, but it could have been to anywhere (almost) in memory. I implore you to rather think in terms of a pointer pointing to the first element of an array (*ptr==array[0]), and not in terms of an array.

Is it somehow implicit so the compiler knows what I want to do so it just accepts and compiles correctly?

I'm not sure if the compiler should compile successfully or not. But you should not rely on that. It's happens often where one could send pointers of pointers around (**ptr), so the compiler is just going to assume you know what you are doing. So you must take great care of how you work with your pointers.

Upvotes: 1

Peter1
Peter1

Reputation: 97

Ok, after trying to solve this for a day or so, I finally found the mistake, it should not be &Data but just Data so it must look like this:

  if(HAL_SPI_TransmitReceive(&hspi3, (uint8_t*)Read_Cmd, (uint8_t *)Data, (Eeprom_Page_Size +3), 5000) != HAL_OK)
  {
  /* Transfer error in transmission process */
  Error_Handler();
  }

I am not sure why that is ?

Upvotes: 0

Related Questions