Jump to content

    
Sign in to follow this  
Chip115

STM32 + SPI EEPROM

Recommended Posts

Всем привет!

Пытаюсь написать алгоритм работы с SPI EEPROM, но из-за недостатка опыта сомневаюсь в правильности алгоритмов, потому требуется помощь.

Контроллер STM32F103C8 (Reference manual)

Память M95M01 (pdf)

В общем, начал с низкоуровневых функций. Настройка SPI2, поднятие преываний на прием и окончание передачи.

Как я понимаю передача и приём идет одновременно. В интернете полно примеров, но там используются всякие костыли типа

while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET);

что, откровенно, вызывает кровь из глаз. Хотя мой быдлокодинг еще больше кровоточит. Ну да ладно, ближе к теме.

 

В общем, функция для отправки байта

typedef enum
{
  SPI_EEPROM_STATUS_BSY,     // Spi is busy
  SPI_EEPROM_STATUS_RDY
} SpiEepromStatus;

typedef struct 
{
  unsigned spiByteReseived: 1;
  unsigned spiByteTransmited: 1;
} SpiState_TypeDef;

SpiEepromStatus ui8EepromSendByte(uint8_t byte)
{
  SpiEepromStatus Status = SPI_EEPROM_STATUS_BSY;
  
  if (SPI2->SR & SPI_SR_TXE)
  {
    SPI2->DR = byte;
    Status = SPI_EEPROM_STATUS_RDY; 
  }
  else    
    Status = SPI_EEPROM_STATUS_BSY;
  
  return Status;
}

 

Смысл такой, что если циклически вызывать

ui8EepromSendByte

и чекать что вернула функция, то можно рулить тем, что бы данные отправлялись тогда, когда предыдущие гарантированно уйдут. Такая конструкция приемлема или есть более интересная реализация?

 

Функция прерывания

void SPI2_IRQHandler (void)
{
    if (SPI2->SR & SPI_SR_RXNE)
      {
           ui8ByteFromSpiEeprom = SPI2->DR;
           vSetSpiEepromFlag (&SpiState, SPI_BYTE_RECEIVED);
     }
    
}

 

vSetSpiEepromFlag взводит флаг в битовом поле (через битбанд). Таким образом происходит обмен мессаджами между функциями.

Реализованное битовое поле

typedef struct 
{
  unsigned spiByteReseived: 1;
  unsigned spiByteTransmited: 1;
} SpiState_TypeDef;

 

В целом, цель поднять FAT на SPI EEPROM и определить её как USB, потому в этом контексте, подобная реализация низкоуровневых функций норм? Или же мне отправляемые/принимаемые данные через кольцевой буфер гонять? Или исходящий поток нет смысла через кольцевой буфер гнать? Вообще, общение с EEPROM постраничное? т.е. прежде чем изменить байт (-ты), я должен прочитать всю страницу, изменить нужную информацию и записать вновь?

Share this post


Link to post
Share on other sites

Если скорость SPI большая, то смысла делать на прерываниях особого нет - проц постоянно будет висеть в обработчике прерывания,

т.к. отправить байт стоит 16 тактов, а только войти в прерывание - 12. Лучше уж поллинг - гораздо проще.

Если хотите по правильному, то используйте DMA.

Share this post


Link to post
Share on other sites

Chip115, скажите, а оно под дебаггером у вас вообще работает?

 

Мне тут нужно было в одном относительно старом проекте, который делался на 4-м Кейле, поменять некоторые дефолтные настройки. К I2C оно не относится, но глюк я поймал именно с I2C!

Сейчас на компе только 5-й, 4-го нет.

Проц - тот-же F103, к нему по I2C подключена 24LC16.

 

Запускаю под дебаггером (JLink-Lite подключен, причем настоящий) - ничего не работает, бне входя в деббагер (но с подключенный JLinkом) - все прекрасно работает.

 

Отставил старую программу, набросал в калокубе с халом только работу с I2C и епромкой - абсолютно тоже самое! Под дебаггаром все функции I2C выходят по таймауту, с еепромки читабтся нули и в нее ничего не пишется.

Без входа в дебаггер - все ОК.

 

WTF?!

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this