2024-09-23 05:05 AM
Hi Guys,
is it possible to configure a peripheral in CubeMX without assigning all the pins (usually) required for that peripheral. This is a quite typical scenario, if a peripheral is used other than originally intended.
E.g. I like to use I2S for efficiently and precisely generating the DATA signal for WS2812's or similar addressable LEDs. In this scenario only the I2S_SD line is required and I don't want to "lose" the additional pins by configuring them as I2S pins. But if I give one of the I2S pins another function, it will automatically disable the peripheral.
Is there a way around this except for configuring the peripheral manually?
Cheers,
D.Frejek
Solved! Go to Solution.
2024-09-23 07:32 AM
Hello @dfrejek ,
I think it's not possible to reset one of the pins after setting the peripheral as it disables it.
One of the solution is to de-init the unused GPIOs in the HAL_I2S_MspInit() / stm32xxxx_hal_msp.c:
In the last block of /* USER CODE BEGIN SPI1_MspInit 1 */ /* USER CODE END SPI1_MspInit 1 */
/**I2S1 GPIO Configuration
PG10 ------> I2S1_WS
PB4 (NJTRST) ------> I2S1_SDI
PG11 ------> I2S1_CK
PB5 ------> I2S1_SDO
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
}
Hope it helps.
2024-09-23 07:32 AM
Hello @dfrejek ,
I think it's not possible to reset one of the pins after setting the peripheral as it disables it.
One of the solution is to de-init the unused GPIOs in the HAL_I2S_MspInit() / stm32xxxx_hal_msp.c:
In the last block of /* USER CODE BEGIN SPI1_MspInit 1 */ /* USER CODE END SPI1_MspInit 1 */
/**I2S1 GPIO Configuration
PG10 ------> I2S1_WS
PB4 (NJTRST) ------> I2S1_SDI
PG11 ------> I2S1_CK
PB5 ------> I2S1_SDO
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
}
Hope it helps.
2024-09-23 11:16 AM
I do not know about in special I²C, but for SPI or UART there are various transmit/receive only modes, pins for other channel side are not required. And e.g. the hand shake lines for USART are also not mandatory to use as them, as far I know you can use these pins for other stuff.
2024-09-23 11:35 PM
Hi,
thanks for the reply. This is not exactly really a pretty solution, since it would look a bit confusing and create "dead" / redundant code, yet it will do the job.
In addition, this does not allow to configure the pin as something else in CubeMX, but as long as these pins are only used as "dumb" I/Os this should be fine.
It's a bit of a shame, there is no nicer way to do this. My use case is quite specific though, so I totally understand, why such a thing is not implemented, as it would be hardly useful to most people.
Cheers,
D. Frejek
2024-09-23 11:42 PM
In my case, that’s not an available option, since CubeMX does not know of a I2S configuration with only the data line.
Normally, this configuration would be useless. But, the I2S can be used to create a bit stream with precisely controllable timings. And this can make this configuration very useful to bitbang / emulate various serial protocols.
2024-09-24 07:32 AM
>>>> But, the I2S can be used to create a bit stream with precisely controllable timings.
Actualy I2S has much less precision over SPI, since it has more clock dividers in structure. The only reason to use I2S is to have more bits . I2S allows 32-bits all the time, even 64 if two channels used as one. SPI has 32, or even 16.
Timer configured to run with DMA may be alternative
2024-09-24 11:48 PM
There is another benefit of I2S, which is much more flexibility in selecting the baud rate. While SPI timing might be slightly more accurate, for all chips I know, the baud rate divider divider is only exponential (1, 2, 4, 8, 16, ...).
For I2S you can set an integer divider and on some larger MCUs, there is even a separate PLL for I2S, which can be used to set the baud rate precisely to whatever you want.
A timer with DMA is indeed an alternative, although very inefficient memory-wise.