I am trying to read/write data from ST EEPROM M95640-W
Acording to datasheet, for read operations data command must be formated like:
First is 8-bit instruction "Read from Memory Array": 0x03 (B00000011)
Second is 16-bit address.
But when I send command and data I got this:
And just to check data position with mirrored bits
So I can not find an error in my code, why it send data in that incorrect way. It send 0x20 command except of 0x03. It send 0x48 address except of 0x01 and 0x80 except of 0x81. Looks like I got an incorrect data translation between types uint16_t -> uint8_t*.
So here is the code:
#define EEPROM_SPI hspi1
#define EEPROM_READ 0x03 // Read from Memory Array
/**
* @brief Reads a block of data from the EEPROM.
* @param pBuffer: pointer to the buffer that receives the data read from the EEPROM.
* @param ReadAddr: EEPROM's internal address to read from.
* @param NumByteToRead: number of bytes to read from the EEPROM.
* @retval None
*/
uint8_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t NumByteToRead) {
/*!< Select the EEPROM: Chip Select low */
EEPROM_LED_ON();
EEPROM_CS_LOW();
/*!< Send "Read from Memory" instruction and MSB of WriteAddr */
EEPROM_SendInstruction((uint8_t*)EEPROM_READ, 1);
/*!< Send WriteAddr address byte to read from */
EEPROM_SendInstruction((uint8_t*)ReadAddr, 2);
if (HAL_SPI_Receive_DMA(&EEPROM_SPI, (uint8_t*)pBuffer, NumByteToRead) != HAL_OK) {
Error_Handler();
}
/*!< Deselect the EEPROM: Chip Select high */
EEPROM_CS_HIGH();
EEPROM_LED_OFF();
return 0;
}
void EEPROM_SendInstruction(uint8_t *instruction, uint8_t size) {
while (EEPROM_SPI.State == HAL_SPI_STATE_RESET) {
osDelay(1);
}
if (HAL_SPI_Transmit_DMA(&EEPROM_SPI, (uint8_t*)instruction, (uint16_t)size) != HAL_OK) {
Error_Handler();
}
}
SPI initialization:
static void MX_SPI1_Init(void) {
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
if (HAL_SPI_Init(&hspi1) != HAL_OK) {
Error_Handler();
}
}
UPD1: I did the packet like @Guillaume Michel said and it worked:
UPD2 I published the libriary at Github, writing and reading data is fully functional. Help is welcome to review the code and add some new features.
Your code does not seem to be written to use DMA, so don't use it. Try to use HAL_SPI_Receive
and HAL_SPI_Transmit
rather than HAL_SPI_Receive_DMA
and HAL_SPI_Transmit_DMA
.
The polarity and the phase seem OK, but double check.
I am not sure that the way you call EEPROM_SendInstruction
is correct. Try this instead:
uint8_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t NumByteToRead) {
uint8_t tmpBuf[2];
/*!< Select the EEPROM: Chip Select low */
EEPROM_LED_ON();
EEPROM_CS_LOW();
/*!< Send "Read from Memory" instruction and MSB of WriteAddr */
tmpBuf[0] = EEPROM_READ;
EEPROM_SendInstruction(tmpBuf, 1);
/*!< Send WriteAddr address byte to read from */
tmpBuf[0] = (uint8_t)(ReadAddr<<8);
tmpBuf[1] = (uint8_t)ReadAddr;
EEPROM_SendInstruction(tmpBuf, 2);
if (HAL_SPI_Receive_DMA(&EEPROM_SPI, (uint8_t*)pBuffer, NumByteToRead) != HAL_OK) {
Error_Handler();
}
/*!< Deselect the EEPROM: Chip Select high */
EEPROM_CS_HIGH();
EEPROM_LED_OFF();
return 0;
}