Can not blink the LED PA5 on Nucleo board - stm32

Could you please help me to identify where i make the mistake? LED is on PA5 port.
int main(void){
HAL_Init();
SystemClock_Config();
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
while(1){
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
HAL_Delay(5000);
}
}

On microcontrollers pins have multiple functions, which functions is enabled has to be configured by software and sometimes by hardware (pulling pins to VCC or GND,...). PA5 of the STM32L073xZ has alternate functions, this is in the datasheet (https://www.mouser.de/datasheet/2/389/stm32l073v8-956245.pdf) on page 39 and 45, the package of the MCU on the Nucleo L073RZ is LQFP64, cf schematic of the Nucleo in https://www.st.com/content/ccc/resource/technical/document/user_manual/98/2e/fa/4b/e0/82/43/b7/DM00105823.pdf/files/DM00105823.pdf/jcr:content/translations/en.DM00105823.pdf on page 64 (https://www.st.com/content/ccc/resource/technical/document/reference_manual/2f/b9/c6/34/28/29/42/d2/DM00095744.pdf/files/DM00095744.pdf/jcr:content/translations/en.DM00095744.pdf).
i do not know if you have enabled the alternate functions somewhere in the rest of your code however this is possibly the core of the problem. The part of the code you posted is accurate, in https://github.com/TechBreiteneder/00_GPIO_BlinkLED/blob/master/Src/main.c is LED blinking code in a CubeMX project. So possibly you enabled an alternate function on pin PA5, in addition you have to enable other components like the clock system for the MCU to work at all, cf https://riptutorial.com/stm32/example/25059/first-time-setup-with-blink-led-example-using-sw4stm32-and-hal-library . So without knowing your configuration of the MCU it is hard to say where the error is ...
What you should do is to set a defined inital state before toggling something however i think this is not the problem
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN5, GPIO_PIN_RESET);

Related

STM32CubeIDE doesn't generate configuration code (NUCLEO-H745ZI)

I'm new to STM microcontrollers and trying to use the STM32CubeIDE.
The problem is that it doesn't generate the codes that configure the GPIO registers.
More specifically, I'd like to set the PB14 as an output port so that the LED3 can blink.
After this screen, in my understanding, the code to configure PIO registers should be automatically generated in main.c, whether it's for the Cortex-M4 core or M7. However, there was nothing like that. Even the global search for such a code didn't find one. As a result, the code below, which is supposed to toggle the output level for the LED3, just don't work. (It didn't blink.)
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET);
HAL_Delay(1000);
When I manually set the registers as shown below, the LED3 successfully blinks.
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_14;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
I'm using the NUCLEO-H745ZI board.
Edit:
Solved.
For MCUs that have multiple cores, I just had to select the core that I want to put the generated code in, as shown below.

Failing to receive data from UART in DMA mode

I am trying to receive 8 bytes from my pc on my NUCLEO F446RE stm32 board.
Transmitting to the pc works.
The problem is, I am unable to receive data using DMA.
I saw an example with almost the same code and it has worked for the person.
If I use the interrupt mode (just change HAL_UART_Receive_DMA to HAL_UART_Receive_IT, it does work and the RX Complete callback is being called.
Here is the complete main.c. DMA is in circular mode.
main.c
https://pastebin.com/1W4BCjxB
I got it solved, it is actually ridiculous.
So, this is part of the code that CubeMX generates:
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_DMA_Init();
If I order it as follows:
MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
It works!!!
I had the same problem. Here is the solution with using the CubeMX integrated view.
In the CubeMX->Project Manager->Advanced Settings you can select the order of functions to be generated. I moved my MX_DMA_Init to the top to ensure that the DMA is ready before any other peripherals are initialised.
You haven't initialized the DMA variables as well as handler for the DMA interrupt. You will need to do something along these lines
Initialize DMA:
hdma_usart2_rx.Instance = DMA2_Stream1;
hdma_usart2_rx.Init.Channel = DMA_CHANNEL_2;
hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart2_rx.Init.MemInc = DMA_MINC_DISABLE;
hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart2_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart2_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_usart2_rx);
void DMA2_Stream2_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(DMA2_Stream2_IRQn);
HAL_DMA_IRQHandler(&hdma_usart1_rx);
}
HAL_UART_Receive_DMA only starts the DMA and does not handle the interrupt and the data transfer.

STM32: Use USART with character match ISR and DMA buffer

I'm using a STM32L432 device with FreeRTOS and STM32CubeMX.
I try to implement a M2M-Communication via USART based on an ASCII protocol. The protocol sequences can differ in length but have a maximum length and a defined end character ('\r' / 0x0D).
So I thought about collecting all RX-USART data with DMA (like a FIFO) and using the address match isr based on the USART_ICR_CMCF flag to determine an end character.
Initialize USART1 and enable address match isr
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1) {
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */
USART1->CR2 |= 0x0D000000; // \r 0x0D
__HAL_UART_ENABLE_IT(&huart1,UART_IT_CM);
}
}
USART1 isr handler
void USART1_IRQHandler(void) {
if (USART1->ISR & USART_ISR_CMF) {
data = USART1->RDR;
SET_BIT(USART1->ICR,USART_ICR_CMCF);
}
HAL_UART_IRQHandler(&huart1);
}
Right now, the address match isr works fine, but I don't have a idea how to implement the DMA / FIFO support.
BTW:
I was very surprised, that the device doesn't support a USART HW FIFO. Is my idea to use DMA to reproduce the FIFO commonly used?
The point of DMA is to not involve the CPU in every byte being transferred. If your ISR is being called for every byte then CPU gets involved so simultaneously enabling DMA, if at all that is possible, won't yield any performance benefits. Get rid of any one of the two - per byte interrupts or the DMA. If you most definitely want to check for a particular character as it arrives then DMA would not help.
Another popular approach to detect end of input when using arbitrary length input along with DMA is to use the USART idle interrupt. This interrupt is triggered when one byte time (time required to transfer one byte at current baud rate) elapses without any transfer. In this interrupt you can transfer the DMA buffer contents to another memory location then reinitialize DMA for future input and leave. Or you can process the input then and there. You can do whatever you want in the Idle ISR as long as the ISR completes execution quickly.
If your input has large continuous runs of data then the idle interrupt would trigger after a long time and you might have overwritten your buffer by then. You can use other DMA interrupts like Half Complete and Full Complete to handle this. So that can be taken care of too. I personally found this method to be buggy during stress testing. But there is no reason for it to be so, I didn't get enough time to debug it when I tried to use it but you will find articles online about this technique.

I2C, DCMI stops working after waking up from STOP mode in stm32f4

The I2C and DCMI stops working on my custom board after wake up from STOP mode. I deinitialize GPIO's before going into STOP mode. After wake up from STOP for I2C I always get HAL_BUSY for both read and write while for camera on DCMI I get some random data instead of jpeg image. But if I don't deinitialize GPIO's then everything works fine without any problem but there is higher power consumption in STOP mode. Following is my code for GPIO's deinitialization
void MX_GPIO_Deinit()
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pin = GPIO_PIN_All;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
/* Disable GPIOs clock */
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
__HAL_RCC_GPIOH_CLK_DISABLE();
}
Is there any to reset I2C and DCMI properly after waking from STOP mode? Calling functions MX_I2C2_Init() and MX_DCMI_Init() doesn't work. What is the proper way for handling this and make I2C and DCMI work?
Peripherals can be reset using the RCC (Reset and Clock Control).
Find the bits corresponding to the peripherals to be reset in the RCC...RSTR registers, set them to 1, and clear them to 0. E.g. for DCMI, it would be
RCC->AHB2RSTR |= RCC_AHB2RSTR_DCMIRST;
RCC->AHB2RSTR &= ~RCC_AHB2RSTR_DCMIRST;
HAL provides some macros that save you the need to look up the register names, like
__HAL_RCC_DCMI_FORCE_RESET();
__HAL_RCC_DCMI_RELEASE_RESET();
You can find the register bits and the macros for the I2C peripheral in the Reference Manual, or in the HAL headers.

LwIP stack add new driver for KSZ8851SNL ethernet controller

Using STM32CubeMX and Atollic TrueStudio, I created a project with a KSZ8851SNL ethernet controller.
On an STM32H742, I have a driver for the Micrel KSZ8851SNL, and created a micro TCP/IP stack, to test the chip. I got that working very well, but it currentl;y only supports ARP, UDP and ICMP. I can ping in two directions, handle ARP request in both directions, and request NTP time from internet.
Now, I would like to let it work together with LwIP.
I know it needs to be implemented in a file ethernetif.c.
Basically, I used these functions to let the micro setup work:
// Initializes the KSZ8851SNL
uint8_t ksz8851_init(void)
// Send a packet, returns length of received package
// The received length can be checked if we received a packet
uint16_t ksz8851_Receive(uint8_t *pRXData, uint16_t pRXMaxLength)
// Receive a packet
void ksz8851_Send(uint8_t *pTXData, uint16_t pTXLength)
The project is an Atollic TrueStudio project, and I use HAL.
Are above functions sufficient for LwIP?
How do I implement this in LwIP?
I read lots of documentation, but it seems not detailed to this part.
Sources are on hithub:
https://github.com/bkht/STM32H7_HAL_KSZ8851SNL
Thanks a lot for helping me out!
One more thing other than uncomment // MX_LWIP_Init();.
I have an STM32H743 Nucleo-144 and tried to run it(commit number f8ff06c2c17f3d6dacbff8c2fd8eb95591a0c224), too. However, it was stuck in this loop: https://github.com/bkht/STM32H7_HAL_KSZ8851SNL/blob/master/Drivers/KSZ8851SNL/Src/KSZ8851SNL.c#L443-L506 because of a failure of reading chip ID with ksz8851_reg_read() . Then I dig deeper in to the source code, and here is a possible solution:
Change the GPIO setting of SPI2's NSS/CS pin
In the .ioc file(if you are still generating workspace with it), set SPI2's "Hardware NSS Signal" to "Hardware NSS Output Signal" in
https://github.com/bkht/STM32H7_HAL_KSZ8851SNL/blob/master/Nucleo-H743ZI_Jack_013_tcp_KSZ8851SNL_Test.ioc.
Or change the source directly by giving PB12 a different GPIO-setting as
GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
Uncomment the macro of SPI2 CS Pin https://github.com/bkht/STM32H7_HAL_KSZ8851SNL/blob/master/Drivers/KSZ8851SNL/Inc/KSZ8851SNL.h#L55-L67 and the usage of them(// RESET_SPI_CS_PIN(); & // SET_SPI_CS_PIN();) in https://github.com/bkht/STM32H7_HAL_KSZ8851SNL/blob/master/Drivers/KSZ8851SNL/Src/KSZ8851SNL.c
Then, the correct chip ID will be fetched.
Clement