HAL_UART_RxCpltCallback() not getting executed - interrupt

I want to send 10 bytes of data through UART loopback by interrupt mode. Though I'm able to receive the data, I don't understand why my HAL_UART_RxCpltCallback() is not getting executed. But my HAL_UART_TxCpltCallback(), is getting executed every time after a byte of data is transferred. I've generated code through cubeMX. I've enabled the USART2 global interrupt. My Control Register(CR1) for my USART2 is 0x300c. That is, UE,M,TE,RE bits are only set. The TXIE, TCIE bits are NOT set in the CR1 Register.
Now,
What does "global" in global interrupt mean here? Does that mean an interrupt is generated from any one of the 10 sources(mentioned in the data sheet like, Tx complete, Rx buffer full etc)?
None of the bits corresponding to interrupts are enabled in CR1 register. But the control is going to HAL_UART_TxCpltCallback() every time it transfers a byte of data. Why does this happen?
Please unveil the mystery.
PS: I'm using STM32F407G-DISC1 board, Attolic Truestudio IDE, Ubuntu 16.04 OS.
UART_HandleTypeDef huart2;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
uint8_t tx_data[] = {0,1,2,3,4,5,6,7,8,9};
uint8_t rx_data[10];
int main(void)
{
int i=0;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
while (1)
{
HAL_UART_Transmit_IT(&huart2, &tx_data[i], 10);
HAL_Delay(1500);
HAL_UART_Receive_IT(&huart2, &rx_data[i] , 10);
HAL_Delay(1500);
if((xferCnt==10) || (rxCnt==10))
break;
else
i++;
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
xferCnt++;
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
rxCnt++;
}

Related

Interrupt handler won't run

I'm working on an stm32l467 and trying to run an ISR when i push the user-push-button. Everything looks to be setup correctly. I have looked at the registers in the debugger (Keil uV) and everything looks good, but when i push the button I end up in the default handler and can't understand why the handler is not running.
Running in the debugger i can see that when i push the button, i get an interrupt-pending (EXTI->PR1) flag, but the code then jumps to the the default handler. I can't see what i'm missing. I know there are easier ways to setup interrupts using the HAL layer, i'm just trying to understand what registers must be accessed from a low-level.
Can anyone suggest a missing step to this?
#include <stm32l4xx.h>
#define DELAY 1
void delay1Hz(void);
bool buttonInterrupt = false;
int main(void)
{
__disable_irq();
/* Configure the clocks */
RCC->CR &= 0xFFFFFF07; //Clear ~MSIRANGE bits and MSIRGSEL bit
RCC->CR |= 0x00000088; //Set MSI to 16MHz and MSIRGSEL bit
RCC->AHB2ENR |= 0x00000001; //Enable PA5 clocks
/* Enable PA0 for output */
GPIOA->MODER &= 0xFFFFF3FF; //Clear GPIOA[5] MODER bits
GPIOA->MODER |= 0x00000400; //Enable GPIOA[5] for output
RCC->AHB2ENR |= 0x4; //ENABLE GPIOC port clk
GPIOC->MODER &= 0xF3FFFFFF; //Clear GPIOC[13] for input mode
RCC->APB2ENR |= 1; //Enable SYSCFG clk
SYSCFG->EXTICR[3] &= ~0x00F0; //CLEAR_BIT the EXTI[13] bits
SYSCFG->EXTICR[3] |= 0x20; //Enable GPIOC for EXTI[13]
EXTI->IMR1 |= 0x2000; //Unmask EXTI13
EXTI->FTSR1 |= 0x2000; //Enable falling edge trigger on pb
NVIC_EnableIRQ(EXTI15_10_IRQn); //Enable EXTI15-to-10 interrupts
__enable_irq();
for (;;)
{
if(buttonInterrupt == true) {
//flash LED's (doesn't get here)
}
}
}
void initTim2() {
//timer 2 code - not causing a problem
}
void delay1Hz() {
//delay code - not interrupt controlled
}
/* This doesn't run */
void EXTI15_10_IRQHandler(void) {
buttonInterrupt = true;
EXTI->PR1 = 0x2000;
}
Never mind: There seems to be some problem with a delay i have with timer-2. It's not using interrupts, so i'm surprised it's causing trouble. But if i take it out and use a different delay, the interrupt from the above code works fine. It's an odd one.

STML4 USB virtual com port

I have the nucleo board (nucleo-L4R5ZI) and want to write a code to be able to send data from a uC to a PC via the USB. I followed some tutorials, used STM32CubeMx, other solutions found across the Internet, but anyways I failed. I can open the vcp on the PC side (using Hterm, TeraTerm and Realterm), but cannot get any data.
I use Eclipse and the buildin debugger, which I flashed to JLink.
The main loop:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USB_DEVICE_Init();
HAL_Delay(10000);
uint8_t HiMsg[] = "0123456789987654321001234567899876543210\r\n";
while (1)
{
if( CDC_Transmit_FS(HiMsg, 20) == USBD_OK )
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7); // blue LED
}
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14); // red LED
HAL_Delay(1000);
}
}
After executing this function, the blue LED lights only once and never changes its state (does not blink). It means that the CDC_Transmit_FS(...) returns USBD_OK only once, and next calls give USBD_Busy.
The MX_USB_DEVICE_Init() looks as follow:
void MX_USB_DEVICE_Init(void)
{
USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);
USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC);
USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);
USBD_Start(&hUsbDeviceFS);
USBD_CDC_Init (&hUsbDeviceFS, &USBD_CDC); // I need to init it somewhere so I think here is a good place
}
The CDC_Transmit_FS looks like that:
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
CDC_Init_FS();
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
CDC_Init_FS();
/* USER CODE END 7 */
return result;
}
Does anyone know how to make it running? What do I miss?
Best,
This part look suspicious:
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
CDC_Init_FS();
The call to CDC_Init_FS() probably kills the packet before it had a chance to be sent to the host.
SO... I found the solution!
I can confirm that the code above works (just remove the CDC_Init_FS)!
Acctully, it was a driver problem. for windows 10 you also need to install it despide what's written in the reference

stm32L476RG - how to execute the bootloader from firmware

I am working on a NUCLEO-L476RG board, trying to start the bootloader from my firmware code but its not working for me. here is the code that i am trying to execute :
#include "stm32l4xx.h"
#include "stm32l4xx_nucleo.h"
#include "core_cm4.h"
#include "stm32l4xx_hal_uart.h"
GPIO_InitTypeDef GPIO_InitStructure;
UART_HandleTypeDef UartHandle;
UART_InitTypeDef UART_InitStructre;
void BootLoaderInit(uint32_t BootLoaderStatus){
void (*SysMemBootJump)(void) = (void (*)(void)) (*((uint32_t *) 0x1FFF0004));
if(BootLoaderStatus == 1) {
HAL_DeInit(); // shut down running tasks
// Reset the SysTick Timer
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL =0;
__set_PRIMASK(1); // Disable interrupts
__set_MSP((uint32_t*) 0x20001000);
SysMemBootJump();
}
}
int main(void)
{
HAL_Init();
__GPIOC_CLK_ENABLE();
GPIO_InitStructure.Pin = GPIO_PIN_13;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
while (1) {
if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13)) {
BootLoaderInit(1);
}
}
return 0;
}
What i hope to get after the execution of the firmware is that i can connect to the board with a UART and send commands/get responses from the bootloader. the commands i am trying to use come from here: USART protocol used in the STM32 bootloader.
I don't see and response from the board after connecting with the UART.
Here are some ideas taken from the answers to this question.
HAL_RCC_DeInit();
This is apparently needed to put the clocks back into the state after reset, as the bootloader expects them to be.
__HAL_REMAPMEMORY_SYSTEMFLASH();
Maps the system bootloader to address 0x00000000
__ASM volatile ("movs r3, #0\nldr r3, [r3, #0]\nMSR msp, r3\n" : : : "r3", "sp");
Set the stack pointer from bootloader ROM. Where does your 0x20001000 come from? If it's an arbitrary value, then the stack can clobber the bootloader's variables.
Then there is this alternate solution:
When I want to jump to the bootloader, I write a byte in one of the
backup register and then issue a soft-reset. Then, when the processor
will restart, at the very beginning of the program, it will read this
register.
Note that you need LSI or LSE clock for accessing the backup registers.
Try to avoid using __set_MSP(), as current implementation of this function does NOT allow you to change MSP if it is also the stack pointer which you currently use (and you most likely are). The reason is that this function marks "sp" as clobbered register, so it will be saved before and restored afterwards.
See here - STM32L073RZ (rev Z) IAP jump to bootloader (system memory)
Find your bootloader start address from the reference manual.
Then use the following code.
Make sure you have cleaned and disabled the interrupts before do so.
/* Jump to different address */
JumpAddress = *(__IO uint32_t*) (BootloaderAddress + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();
Please have a look at Official STM32 AppNote as well.

Cannot transmit every characters through UART

I am using stm32f0 MCU.
I would like to transmit every single byte received from the uart out of the uart. I am enabling an interrupt on every byte received from uart.
My code is quite simple.
uint8_t Rx_data[5];
//Interrupt callback routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) //current UART
{
HAL_UART_Transmit(&huart1, &Rx_data[0], 1, 100);
HAL_UART_Receive_IT(&huart1, Rx_data, 1); //activate UART receive interrupt every time on receiving 1 byte
}
}
My PC transmits ASCII 12345678 to stm32. If things work as expected, the PC should be receiving 12345678 back. However, the PC receives 1357 instead. What is wrong with the code?
Reenabling interrupts may be inefficient. With a couple of modifications it is possible to keep the interrupt active without needing to write the handler all over again. See the example below altered from the stm32cubemx generator.
/**
* #brief This function handles USART3 to USART6 global interrupts.
*/
void USART3_6_IRQHandler(void)
{
InterruptGPS(&huart5);
}
void InterruptGPS(UART_HandleTypeDef *huart) {
uint8_t rbyte;
if (huart->Instance != USART5) {
return;
}
/* UART in mode Receiver ---------------------------------------------------*/
if((__HAL_UART_GET_IT(huart, UART_IT_RXNE) == RESET) || (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE) == RESET)) {
return;
}
rbyte = (uint8_t)(huart->Instance->RDR & (uint8_t)0xff);
__HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
// do your stuff
}
static void init_gps() {
__HAL_UART_ENABLE_IT(&huart5, UART_IT_RXNE);
}
You should make a tx array buffer as well, and use interrupt for writing as well (The first write if not enabled yet, should be sent immediately).
There should be examples of this for STM32 around.
You should probably switch the two lines: Transmit and Receive. The Transmit function waits for a timeout to send the character, in meantime the next received character is missed.

Cortex M-0: Simple external interrupt

I'm trying to set up an external interrupt on my LPC812 uC. I've made the following code
#include "LPC8xx.h"
#define RLED 7 // red LED
bool pause = false;
void PININT0_IRQHandler(void)
{
pause = !pause;
}
int main(void) {
LPC_GPIO_PORT->DIR0 |= 1<<RLED; // set pin as output
LPC_GPIO_PORT->SET0 = 1<<RLED;
NVIC_EnableIRQ(PININT0_IRQn);
while (1)
{
if(!pause)
{
LPC_GPIO_PORT->CLR0 = 1<<RLED;
}
}
}
But it isn't working. Am I missing something?
I'm not familiar with NXP MCUs.
But at least place break piont inside PININT0_IRQHandler, to understand clearly that interrupt is not generated.
Also it will be nice to clear interrupt flag inside handler.
Some peripherals need interrupt permission in peripheral registers in addition to NVIC setup.
Did you setup input pin somewhere?
Your code only initialize GPIO 7 pin as output.