I’m working on a program to transmit data over SPI1 and SPI2 using DMA. For output I only use each peripheral’s CLK and MOSI lines. SPI1 and SPI2 differ only in the exact data being sent—their configurations and the number of bytes are identical.
Also, when driving the lines I first need to bit-bang them, so I disable the peripheral, toggle the pins by software, and then re-enable the peripheral.
With an oscilloscope I confirmed that SPI1’s CLK and MOSI, and SPI2’s CLK, all switch as expected—but SPI2’s MOSI never toggles correctly.
I believe the peripheral setup is correct, yet when I remap SPI2-MOSI from PA4 to PA10, it works perfectly.
Below, (1) is the code that was active when SPI2-MOSI was on PA4 (no output), and (2) is the code active when on PA10 (correct output).
The PCB layout is already fixed, so if PA4 can’t serve as SPI2-MOSI it’s a serious problem.
Now, I'm using Nucleo-G071RB for test.
Any insights would be greatly appreciated.
InitialConfig bellow code
/****************************/
/** SPI1 GPIO Configuration */
/****************************/
/* PA5 ------> SPI1_SCK */
/* PA7 ------> SPI1_MOSI */
LL_SPI_InitTypeDef SPI1_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct_SPI1 = {0};
/* Peripheral clock enable */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
GPIO_InitStruct_SPI1.Pin = LL_GPIO_PIN_5;
GPIO_InitStruct_SPI1.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct_SPI1.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct_SPI1.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct_SPI1.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct_SPI1.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct_SPI1);
GPIO_InitStruct_SPI1.Pin = LL_GPIO_PIN_7;
GPIO_InitStruct_SPI1.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct_SPI1.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct_SPI1.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct_SPI1.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct_SPI1.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct_SPI1);
/* SPI1 DMA Init */
LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_1, LL_DMAMUX_REQ_SPI1_TX);
LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)&SPI1->DR);
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_MEDIUM);
LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MODE_NORMAL);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_BYTE);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_BYTE);
/* SPI1 parameter configuration*/
SPI1_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
SPI1_InitStruct.Mode = LL_SPI_MODE_MASTER;
SPI1_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
SPI1_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI1_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
SPI1_InitStruct.NSS = LL_SPI_NSS_SOFT;
SPI1_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8; /* SYSCLK32MHz ÷ 8 = 4MHz*/
SPI1_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
SPI1_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI1_InitStruct.CRCPoly = 7;
LL_SPI_Init(SPI1, &SPI1_InitStruct);
LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
LL_SPI_DisableNSSPulseMgt(SPI1);
LL_SPI_Enable(SPI1);
LL_SPI_EnableDMAReq_TX(SPI1);
/*****************************/
/** SPI2 GPIO Configuration **/
/*****************************/
/* PA0 ------> SPI2_SCK */
/* PA4 ------> SPI2_MOSI */
LL_SPI_InitTypeDef SPI2_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct_SPI2 = {0};
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
GPIO_InitStruct_SPI2.Pin = LL_GPIO_PIN_0;
GPIO_InitStruct_SPI2.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct_SPI2.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct_SPI2.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct_SPI2.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct_SPI2.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct_SPI2);
GPIO_InitStruct_SPI2.Pin = LL_GPIO_PIN_4; //(1)when using PA4 as SPI2_MOSI
// GPIO_InitStruct_SPI2.Pin = LL_GPIO_PIN_10; //(2)when using PA10 as SPI2_MOSI
GPIO_InitStruct_SPI2.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct_SPI2.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct_SPI2.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct_SPI2.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct_SPI2.Alternate = LL_GPIO_AF_1; //(1)when using PA4 as SPI2_MOSI
// GPIO_InitStruct_SPI2.Alternate = LL_GPIO_AF_0; //(2)when using PA10 as SPI2_MOSI
LL_GPIO_Init(GPIOA, &GPIO_InitStruct_SPI2);
/* SPI2 DMA Init */
LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_2, LL_DMAMUX_REQ_SPI2_TX);
LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_2, (uint32_t)&SPI2->DR);
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_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);
/* SPI2 parameter configuration*/
SPI2_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
SPI2_InitStruct.Mode = LL_SPI_MODE_MASTER;
SPI2_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
SPI2_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI2_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
SPI2_InitStruct.NSS = LL_SPI_NSS_SOFT;
SPI2_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8; /* SYSCLK32MHz ÷ 8 = 4MHz*/
SPI2_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
SPI2_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI2_InitStruct.CRCPoly = 7;
LL_SPI_Init(SPI2, &SPI2_InitStruct);
LL_SPI_SetStandard(SPI2, LL_SPI_PROTOCOL_MOTOROLA);
LL_SPI_DisableNSSPulseMgt(SPI2);
LL_SPI_Enable(SPI2);
LL_SPI_EnableDMAReq_TX(SPI2);
below code are function of changing to bitbangmode.
/**************************************************/