2024-04-29 08:46 AM
- STM32G071R8T6, DMA chan 1 ADC's, DMA chan 2 SPI TX, DMA chan 3 SPI RX and DMA chan 4 DAC
- Tested the SPI configuration without the DMA to a SPI EEPROM and it works.
Once the DMA configuration was used, we do not see any data being transmitted.
The initial DMA based communication to the EEPROM is a read command, address and then 0x55 data so that we clock the EEPROMs response back. The Chip Select to the EEPROM is done manually. Because the initial testing done wrote directly to the SPI registers, it seems like something in the configuration of DMA to SPI is not correct. We have used the STM32Cube Repository version STM32Cube_FW_G0_V1.6.1 for Low Level examples but the DMA and SPI are not tired together for the G071(they have HAL based.)
- If we remove the call to LL_DMAMUX_SetRequestID(), which is needed because the G071 has a DMA mux, we will receive a DMA1_Channel2_3_IRQHandler interrupt after the TX DMA is triggered. There is still no data being transmitted but the interrupt fires.
Any help is appreciated.
void SPI_LowLevel_Init(void)
{
LL_GPIO_InitTypeDef GPIO_InitStructure = {0};
// GPIOA and GPIOC Periph clock's have already been enabled.
/* SPI1 EEPROM Periph clock enable */
//RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
/* Configure EEprom pins: MISO and MOSI */
GPIO_InitStructure.Pin = SPI1_MISO; // ==> GPIO_PA11
GPIO_InitStructure.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStructure.Speed = LL_GPIO_SPEED_HIGH;
GPIO_InitStructure.Pull = LL_GPIO_PULL_DOWN;
GPIO_InitStructure.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.Pin = SPI1_MOSI; // ==> GPIO_PA12
GPIO_InitStructure.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStructure.Speed = LL_GPIO_SPEED_HIGH;
GPIO_InitStructure.Pull = LL_GPIO_PULL_DOWN;
GPIO_InitStructure.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(GPIOA, &GPIO_InitStructure);
// Configure EEprom pins: SCLK
GPIO_InitStructure.Pin = SPI1_SCLK; // ==> GPIO_PD8
GPIO_InitStructure.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStructure.Speed = LL_GPIO_SPEED_HIGH;
GPIO_InitStructure.Pull = LL_GPIO_PULL_DOWN;
GPIO_InitStructure.Alternate = LL_GPIO_AF_1;
LL_GPIO_Init(GPIOD, &GPIO_InitStructure);
/* Configure sEE_CS_PIN pin: sEE Card CS pin */
GPIO_InitStructure.Pin = SPI1_CS; // ==> GPIO_PD9
GPIO_InitStructure.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStructure.Speed = LL_GPIO_SPEED_HIGH;
GPIO_InitStructure.Pull = LL_GPIO_PULL_DOWN;
LL_GPIO_Init(GPIOD, &GPIO_InitStructure);
/* Insure the EEPROM Chip Select high */
LL_GPIO_SetOutputPin(GPIOD, SPI1_CS);
// GPIO_PinAFConfig parameter #3 possible values.
// This parameter can be one of the following value:
// SCLK PD8 pin 40 @arg USART3_TX, SPI1_SCK/I2S1_CK, LPTIM1_OUT
// MISO PA11 pin 43 @arg SPI1_MISO/I2S1_MCK, USART1_CTS, TIM1_CH4, TIM1_BKIN2, I2C2_SCL, COMP1_OUT
// MOSI PA12 pin 44 @arg SPI1_MOSI/I2S1_SD, USART1_RTS_DE_CK, TIM1_ETR, I2S_CKIN, I2C2_SDA, COMP2_OUT
// PD8(SPI SCLK) --> GPIO_AF_1 for SPI1, Datasheet(table 16) lists AF pin for SPI as: SPI1_SCK/I2S3_CK
LL_GPIO_SetAFPin_0_7(GPIOD, SPI1_SCLK, LL_GPIO_AF_1);
// PA11(SPI MISO) --> GPIO_AF_0 for SPI3, Datasheet(table 13) lists AF pin for SPI as: SPI1_MISO/I2S3ext_SD
LL_GPIO_SetAFPin_0_7(GPIOA, SPI1_MISO, LL_GPIO_AF_0);
// PA12(SPI MOSI) --> GPIO_AF_0 for SPI1, Datasheet(table 13) lists AF pin for SPI as: SPI1_MOSI/I2S3_SD
LL_GPIO_SetAFPin_0_7(GPIOA, SPI1_MOSI, LL_GPIO_AF_0);
// SPI NSS --> GPIO_AF_6 for SPI3, Datasheet lists AF pin for SPI as: SPI1_NSS
//GPIO_PinAFConfig(GPIOA, GPIO_PinSource15, GPIO_AF_6);
/* SPI Config */
// SPI bus speed should be 64Mhz/16 prescale = 4Mhz
LL_SPI_InitTypeDef SPI_InitStruct = {0};
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.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV16;
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
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_DisableNSSPulseMgt(SPI1);
LL_SPI_SetRxFIFOThreshold(SPI1, LL_SPI_RX_FIFO_TH_QUARTER);
// Configure SPI1 DMA transfer interrupts
// Enable DMA TX Interrupt
LL_SPI_EnableDMAReq_TX(SPI1);
// Enable DMA RX Interrupt
LL_SPI_EnableDMAReq_RX(SPI1);
// DMA channel 2 configuration for Tx of SPI
LL_DMAMUX_SetRequestID(DMAMUX1, LL_DMAMUX_CHANNEL_1, LL_DMAMUX_REQ_SPI1_TX);
LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_2, LL_DMAMUX_REQ_SPI1_TX);
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_2, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PRIORITY_HIGH);
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_HALFWORD);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MDATAALIGN_HALFWORD);
// DMA channel 3 configuration for Rx of SPI
LL_DMAMUX_SetRequestID(DMAMUX1, LL_DMAMUX_CHANNEL_2, LL_DMAMUX_REQ_SPI1_RX);
LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_3, LL_DMAMUX_REQ_SPI1_RX);
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_3, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PRIORITY_HIGH);
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);
// Set DMA transfer addresses of source and destination
// Set DMA transfer size
// Enable DMA transfer interruption: transfer complete
// Enable DMA transfer interruption: half transfer
// Enable DMA transfer interruption: transfer error
LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_2, LL_SPI_DMA_GetRegAddr(SPI1),
(uint32_t)txSpiBuff, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, 1);
// Set DMA transfer addresses of source and destination
// Set DMA transfer size
// Enable DMA transfer interruption: transfer complete
// Enable DMA transfer interruption: half transfer
// Enable DMA transfer interruption: transfer error
LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_3, LL_SPI_DMA_GetRegAddr(SPI1),
(uint32_t)rxSpiBuff, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_3, 1);
/* SPI1 enable */
LL_SPI_Enable(SPI1);
// (5) Enable DMA transfer complete/error interrupts
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_2);
LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_2);
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_3);
LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_3);
}
/*
* @name spi_eeprom_init()
* @brief - A function is to initialize/read the spi eeprom based error log starting
* at page address 3.
*
* @details - Because this is a eeprom chip, we will verify the M95160 chip and then
* read the data via 32 byte page reads.
*
* Usage:
* @PAram[in] - None
* @return - None
*/
void spi_eeprom_init(void)
{
uint8_t errorLogReset = 0;
uint32_t *addr_p, page1ErrorType, page2ErrorType, pageNumber;
HAL_StatusTypeDef currState;
// Set up the read command to the SPI EEPROM.
txSpiBuff[0] = sEE_CMD_READ;
txSpiBuff[1] = ((HIGH_TEMP_LOCKOUT_ADDRESS & 0xFF00) >> 8);
txSpiBuff[2] = (HIGH_TEMP_LOCKOUT_ADDRESS & 0xFF);
txSpiBuff[3] = (0x55);
txSpiBuff[4] = (0x55);
txSpiBuff[5] = (0x55);
txSpiBuff[6] = (0x55);
txSpiBuff[7] = (0x55);
txSpiBuff[8] = (0x55);
txSpiBuff[9] = (0x55);
txSpiBuff[10] = (0x55);
txSpiBuff[11] = (0x55);
txSpiBuff[12] = (0x55);
// !< Select the EEPROM: Chip Select low
LL_GPIO_ResetOutputPin(GPIOD, SPI1_CS);
// Set up the TX SPI DMA
LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_2, LL_SPI_DMA_GetRegAddr(SPI1),
(uint32_t)txSpiBuff, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
// Set up the transfer size which is the read command(3 bytes) plus the data we
// want to read.
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, (EEPROM_PAGE_SIZE_IN_BYTES+3));
// Enable SPI1.
LL_SPI_Enable(SPI1);
// Enable RX and then TX.
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_3);
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
// // In order to read the entire 32 bytes from the chip, add in the 3 bytes of command and address.
// currState = SPI_TransmitReceive_DMA(&spiBus1_handler, txSpiBuff, rxSpiBuff, (EEPROM_PAGE_SIZE_IN_BYTES+3));
// // !< Deselect the EEPROM: Chip Select high
// LL_GPIO_SetOutputPin(GPIOD, SPI1_CS);
while (wTransferState == TRANSFER_WAIT)
{
}
switch (wTransferState)
{
case TRANSFER_COMPLETE :
break;
default :
break;
}
}
Solved! Go to Solution.
2024-04-29 12:55 PM
Appears we had the transmit addresses backwards.
LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_2, (uint32_t)txSpiBuff,
LL_SPI_DMA_GetRegAddr(SPI1), LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
2024-04-29 12:55 PM
Appears we had the transmit addresses backwards.
LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_2, (uint32_t)txSpiBuff,
LL_SPI_DMA_GetRegAddr(SPI1), LL_DMA_DIRECTION_MEMORY_TO_PERIPH);