Всем привет!
Пытаюсь написать алгоритм работы с 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);
}
if (SPI2->SR & SPI_SR_TXE)
{
SPI2->SR &= ~SPI_SR_TXE;
}
}
vSetSpiEepromFlag взводит флаг в битовом поле (через битбанд). Таким образом происходит обмен мессаджами между функциями.
Реализованное битовое поле
- Код:
typedef struct
{
unsigned spiByteReseived: 1;
unsigned spiByteTransmited: 1;
} SpiState_TypeDef;
В целом, цель поднять FAT на SPI EEPROM и определить её как USB, потому в этом контексте, подобная реализация низкоуровневых функций норм? Или же мне отправляемые/принимаемые данные через кольцевой буфер гонять? Или исходящий поток нет смысла через кольцевой буфер гнать? Вообще, общение с EEPROM постраничное? т.е. прежде чем изменить байт (-ты), я должен прочитать всю страницу, изменить нужную информацию и записать вновь?