2020-06-25 09:56 AM
Good day everyone.
I'm trying to get Wiznet made W5500 working with STM32F030 series, using SPI in DMA mode.
Unfortunately, in nSS hardware output mode, SPI bus pulls up nSS line after every transmitted byte (see attached image), while W5500 manual states, that nSS line should be low during whole transaction.
I'm not professional. Using Cube MX for device configuration.
Here is the MX generated code for SPI+DMA setup:
void MX_SPI1_Init(void)
{
LL_SPI_InitTypeDef SPI_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Peripheral clock enable */
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SPI1);
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
/**SPI1 GPIO Configuration
PA4 ------> SPI1_NSS
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = SPI1_nSS_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(SPI1_nSS_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SPI1_SCK_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(SPI1_SCK_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SPI1_MISO_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(SPI1_MISO_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SPI1_MOSI_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(SPI1_MOSI_GPIO_Port, &GPIO_InitStruct);
/* SPI1 DMA Init */
/* SPI1_RX Init */
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_2, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PRIORITY_MEDIUM);
LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MODE_NORMAL);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PDATAALIGN_BYTE);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MDATAALIGN_BYTE);
/* SPI1_TX Init */
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_3, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PRIORITY_VERYHIGH);
LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MODE_NORMAL);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PDATAALIGN_HALFWORD);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MDATAALIGN_HALFWORD);
/* SPI1 interrupt Init */
NVIC_SetPriority(SPI1_IRQn, 1);
NVIC_EnableIRQ(SPI1_IRQn);
SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
SPI_InitStruct.NSS = LL_SPI_NSS_HARD_OUTPUT;
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV64;
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI_InitStruct.CRCPoly = 7;
LL_SPI_Init(SPI1, &SPI_InitStruct);
LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
LL_SPI_EnableNSSPulseMgt(SPI1);
}
Any ideas?
2020-06-26 05:20 PM
Thanks Jan.
Well noted.
Actually the nSS pin (GPIOA Pin4) is configured as a push-pull (alternative) with no pull-up in case of hardware mode, but, according to Wiz850 schematic, there is a separate pull-up resistor on this line. Will keep it in mind.
Now I'm facing another problem. With no regards to nSS mode I use (tried bot hardware and software managed GPIO), SPI transmit function hangs up after sending a set of data. I found that, for some reason, TCIF2 stays 0 and DMA_CNDTR2 register indicates that one byte still left to read, while all data is in. For example I'm trying to read Retry Time-value Register from W5500, and I can see the correct (default) value in last two bits = 0x07D0.
2020-06-26 05:24 PM
2020-06-26 05:28 PM
> LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PDATAALIGN_HALFWORD);
> LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MDATAALIGN_HALFWORD);
If you want to send an odd number of bytes, set the size to byte. Currently it only sends a half word at a time.
2020-06-26 05:59 PM
LL_SPI_SetRxFIFOThreshold(SPI1, LL_SPI_RX_FIFO_TH_QUARTER) helped to sort out the last issue...
2020-06-27 08:59 AM
Hi Jan. Hi TDK.
Thanks a lot for your help, gentlemen! Much appreciated!
Looks like one of the key moments in SPI DMA configuration is FIFO threshold. After setting it to LL_SPI_RX_FIFO_TH_QUARTER everything worked without issues.
Added LL_SPI_SetRxFIFOThreshold(SPI1, LL_SPI_RX_FIFO_TH_QUARTER); after SPI initialization.
The strings
LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PDATAALIGN_HALFWORD);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MDATAALIGN_HALFWORD);
were replaced to
LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PDATAALIGN_BYTE);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MDATAALIGN_BYTE);
soon after the first post.
I managed to get both software and hardware driven nSS working! In second case I had to alter W5500.c file, and change one string in WIZCHIP_WRITE_BUF function:
WIZCHIP.IF.SPI._write_burst(spi_data, 3);
//WIZCHIP.IF.SPI._write_burst(pBuf, len);
WIZCHIP.IF.SPI._read_burst(pBuf, len); //Replaced from _write_burst to _read_burst to be able to use hardware nSS
So far no problems spotted with (hardware driven nSS) SPI speeds up to 18MHz, even if I use 10-15sm long link cable between STM and Wiznet chips.
Pinging the module successfully.