Если я правильно понял, ТС используется SPI для работы с W25Qxxx. Вот простейший вариант реализации доступа к этой микросхеме. Работает на STM32F4.TEPEM писал(а):Есть три неприятные функции в хале, которые я пытаюсь заменить cmsis.
Спойлер
Код: Выделить всё
#define W25Q_GUARD ( 40'000'000 )
////////////////////////////////////////////////////////////////////////////////
uint8
W25Q::SPI_exchange( uint8 _aByte )
{
uint8
tmp8;
int32
guard = W25Q_GUARD;
while( ( spi -> SR & SPI_SR_RXNE ) && ( guard > 0 ) )
{
tmp8 = spi -> DR;
guard--;
};
if( guard <= 0 )
{
theMemoryIsBad = true;
#ifdef DEBUG
log_printf
(
MsgCat::ERR,
"FTP : W25Q : Memory is bad. Line %d.\n", __LINE__
);
#endif
return( 0 );
}
*( volatile uint8 *)&( spi -> DR) = _aByte;
guard = W25Q_GUARD;
while( ( !( spi -> SR & SPI_SR_RXNE ) ) && ( guard > 0 ) )
{
guard--;
}
if( guard <= 0 )
{
theMemoryIsBad = true;
#ifdef DEBUG
log_printf
(
MsgCat::ERR,
"FTP : W25Q : Memory is bad. Line %d.\n", __LINE__
);
#endif
return( 0 );
}
tmp8 = *( volatile uint8*)&( spi -> DR );
return( tmp8 );
}
////////////////////////////////////////////////////////////////////////////////
uint8
W25Q::SPI_readByte( void )
{
if( theMemoryIsBad == true )
{
return( 0 );
}
return( SPI_exchange( 0 ) );
}
////////////////////////////////////////////////////////////////////////////////
uint16
W25Q::SPI_readBytes( uint8* _buff, uint16 _n )
{
if( theMemoryIsBad == true )
{
return( 0 );
}
if( ( _buff == 0 ) || ( _n == 0 ) )
{
return( 0 );
}
uint16
i = _n;
while( i )
{
*_buff = SPI_readByte();
_buff++;
i--;
if( isFault() )
{
return( 0 );
}
}
return( _n );
}
////////////////////////////////////////////////////////////////////////////////
void
W25Q::SPI_writeByte( uint8 _aByte )
{
if( theMemoryIsBad == true )
{
return;
}
SPI_exchange( _aByte );
}
////////////////////////////////////////////////////////////////////////////////
uint16
W25Q::SPI_writeBytes( uint8* _buff, uint16 _n )
{
if( theMemoryIsBad == true )
{
return( 0 );
}
if( ( _buff == 0 ) || ( _n == 0 ) )
{
return( 0 );
}
uint16
i = _n;
while( i )
{
SPI_writeByte( *_buff );
_buff++;
i--;
if( isFault() )
{
return( 0 );
}
}
return( _n );
}
////////////////////////////////////////////////////////////////////////////////
bool
W25Q::isFault( void )
{
return( theMemoryIsBad );
}
////////////////////////////////////////////////////////////////////////////////
Спойлер
Код: Выделить всё
...
spi -> CR1 =
( 0 << SPI_CR1_BIDIMODE_Pos ) | // 15
( 0 << SPI_CR1_BIDIOE_Pos ) | // 14
( 0 << SPI_CR1_CRCEN_Pos ) | // 13
( 0 << SPI_CR1_CRCNEXT_Pos ) | // 12
( 0 << SPI_CR1_DFF_Pos ) | // 11
( 0 << SPI_CR1_RXONLY_Pos ) | // 10 Fullduplex
( 1 << SPI_CR1_SSM_Pos ) | // 9 Software slave management disabled
( 1 << SPI_CR1_SSI_Pos ) | // 8
( 0 << SPI_CR1_LSBFIRST_Pos ) | // 7 MSB передается первым
( 0 << SPI_CR1_SPE_Pos ) | // 6 Пока _не_ включаем SPI!
( br << SPI_CR1_BR_Pos ) | // 5..3 делитель шины для тактирования SPI;
( 1 << SPI_CR1_MSTR_Pos ) | // 2 Master
( 0 << SPI_CR1_CPOL_Pos ) | // 1 полярность тактового сигнала
( 0 << SPI_CR1_CPHA_Pos ); // 0 Фаза тактового сигнала
spi -> CR2 = \
( 0 << SPI_CR2_TXEIE_Pos ) | // Tx buffer empty interrupt enable
( 0 << SPI_CR2_RXNEIE_Pos ) | // RX buffer not empty interrupt enable
// This bit controls the generation of an interrupt when an error
// condition occurs )(CRCERR, OVR, MODF in SPI mode, FRE in TI mode and
// UDR, OVR, and FRE in I2S mode).
( 0 << SPI_CR2_ERRIE_Pos ) |
( 0 << SPI_CR2_FRF_Pos ) | // 0/1 - Motorola/TO mode
( 0 << SPI_CR2_SSOE_Pos ) | // SS output enable
( 0 << SPI_CR2_TXDMAEN_Pos ) | // Tx buffer DMA enable
( 0 << SPI_CR2_RXDMAEN_Pos ); // Rx buffer DMA enable
spi -> CR1 |= ( 1 << SPI_CR1_SPE_Pos );
...