2024-10-30 08:46 AM - edited 2024-10-30 11:32 AM
The code I wrote for the B-L072Z-LRWAN1 is supposed to count pulses on a falling-edge external interrupt pin. The pulse source is an Arduino which toggles its GPIO on and off every 5ms, for a 10ms pulse period. after 6 seconds, the B-L072Z-LRWAN1 transmits the accumulated pulses to a receiving B-L072Z-LRWAN1 device (using proprietary peer-to-peer communication [confirmed to work properly]), which after 6 seconds should receive a count of 600 pulses. The 6 second timer has been confirmed to trigger a callback every 6 seconds.
My issue is that only 300 pulses are being send, which implies that the interrupt is only being called or incrementing every other time. There is an IoT bridge which takes the pulse input from both the arduino and the receiving STM32 device, and displays the pulse count on an IoT platform. the graph shows that the pulse rate for the STM32 is exactly half of what is coming from the Arduino. After debugging, I confirmed that the sending device is sending the wrong number of 300 pulses. Can anyone tell me the reason for this?
Here is a screenshot of the gpio configuration:
here is the cubeMX configuration function:
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, PA15_RESERVED_Pin|PA12_RESERVED_Pin|PA1_RESERVED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GREEN_LED_Pin|BLUE_LED_Pin|RED_LED_Pin|TCXO_PWR_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, PC1_RESERVED_Pin|PC0_RESERVED_Pin|PC2_RESERVED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : PA15_RESERVED_Pin PA12_RESERVED_Pin PA1_RESERVED_Pin */
GPIO_InitStruct.Pin = PA15_RESERVED_Pin|PA12_RESERVED_Pin|PA1_RESERVED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : GREEN_LED_Pin BLUE_LED_Pin RED_LED_Pin TCXO_PWR_Pin */
GPIO_InitStruct.Pin = GREEN_LED_Pin|BLUE_LED_Pin|RED_LED_Pin|TCXO_PWR_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : PB9 PB8 PB15 PB11
PB12 PB10 */
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_8|GPIO_PIN_15|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : PA14 PA10 PA13 PA8
PA11 PA9 PA0 PA5 */
GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_13|GPIO_PIN_8
|GPIO_PIN_11|GPIO_PIN_9|GPIO_PIN_0|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PB4_RESERVED_Pin PB1_RESERVED_Pin TEST_RANGE_Pin PB0_RESERVED_Pin */
GPIO_InitStruct.Pin = PB4_RESERVED_Pin|PB1_RESERVED_Pin|TEST_RANGE_Pin|PB0_RESERVED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : PC13 PC14 PC15 */
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : PC1_RESERVED_Pin PC0_RESERVED_Pin PC2_RESERVED_Pin */
GPIO_InitStruct.Pin = PC1_RESERVED_Pin|PC0_RESERVED_Pin|PC2_RESERVED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : PH0 PH1 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
/*Configure GPIO pin : PULSE_INPUT_Pin */
GPIO_InitStruct.Pin = PULSE_INPUT_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(PULSE_INPUT_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : ENTER_SETUP_Pin */
GPIO_InitStruct.Pin = ENTER_SETUP_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(ENTER_SETUP_GPIO_Port, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI0_1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
HAL_NVIC_SetPriority(EXTI2_3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI2_3_IRQn);
HAL_NVIC_SetPriority(EXTI4_15_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
here is the interrupt callback function:
//this function is called when an external interrupt is triggered
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/*if the interrupt is triggered from the pulse input pin, increment the pulse
counter*/
if(GPIO_Pin == PULSE_INPUT_Pin)
pulseCount++;
}
for good measure, here is the code for the arduino which sends the pulses to the STM32 (sorry in advance; arduino sucks, I know):
#define ledPin 13
#define pulse_1 4
#define pulse_2 5
#define PULSE_WIDTH 5000 //5 mS
uint32_t timestamp = 0;
bool state = LOW;
void setup() {
// put your setup code here, to run once:
pinMode(ledPin, OUTPUT);
pinMode(pulse_1, OUTPUT);
pinMode(pulse_2, OUTPUT);
digitalWrite(pulse_1, LOW);
digitalWrite(pulse_2, LOW);
digitalWrite(ledPin, LOW);
timestamp = micros();
}
void loop() {
if((micros() - timestamp) >= PULSE_WIDTH)
{
digitalWrite(pulse_1, state);
digitalWrite(pulse_2, state);
timestamp = micros();
digitalWrite(ledPin, state);
(state == HIGH) ? state = LOW : state = HIGH;
}
}
And here is what is showing up on the IoT platform. Sometimes the controller sends the correct 600 pulses, and sometimes it sends 300. The units are not important, as this is only to show if the number of pulses sent match what is sent from the arduino or not. the dip at 11:00 is just from me disconnecting the receiving device for a few minutes.
2024-10-31 01:37 PM - edited 2024-10-31 01:38 PM
OK these kind of responses are absolutely unhelpful.
"(incorrectly - see above)"
above where? what are you referring to? what is incorrect and how?
"Anyway, I believe that all this EXTI stuff is not needed at all."
That is a very nice opinion, but that does not solve the problem at all, or even mention it for that matter. Taking the time to write & troubleshoot my own interrupt handlers is not an option, as would take too much time and just create more issues. If you follow the source code to the IRQ handler, you'll see that it even though it fires the handler for all interrupts on that line, the handler checks the interrupt flag for that pin. This does not cause issues of executing the callbacks incorrectly, it just makes the processor run a bit slower. In any case I want to stick with the HAL. It may run slow, but it's much faster than writing your own drivers and maintaining them. I thought the whole point of the HAL was to cut down production time, and the whole point of the forums was to help troubleshoot issues with STMs hardware and firmware. Telling me to just cut out and rewrite a huge portion of my code because it uses the HAL, with minimal explanation, is no help at all.
2024-10-31 05:22 PM - edited 2024-10-31 05:26 PM
Hi,
Are you saying that you have checked and measured the number of times the IRQ handler has been called, and that is correct?
KInd regards
Pedro
2024-11-01 12:14 AM
What's the clock frequency of your STM32L0?
2024-11-01 01:41 AM
I don't use CubeMX so I don't know how does it present interrupt priorities, but the raw value used in the CMSIS intrinsics or directly in NVIC registers is so that 0 is the highest priority.
JW
2024-11-01 06:13 AM
The sending device has a clock frequency of 131.072 kHz, and the receiving device 32 MHz
2024-11-01 06:15 AM
It is the same in CubeMX. CubeMX is just setting the configuration bits with a GUI, so everything matches the hardware.
2024-11-01 08:05 AM
Hi Pedro,
Currently I have only verified the EXTI_4_15_IRQ_HANDLER by adding a global variable to increment every time it is called. So far, that variable and pulseCount match. If you have any other methods of verification, I would be interested to learn them.
2024-11-01 10:02 AM
I suggested to try to increase the EXTI interrupt priority to highest level. That means to set it to 0, and all other interrupts to non-0.
JW
2024-11-01 10:45 AM - edited 2024-11-01 11:21 AM
Based on the NVIC screenshot I provided in the comments earlier, the only other 0 enabled interrupt is USART2, and unless I am debugging the code, that should not trigger. Still, I will set it to 1 just in case.
2024-11-01 11:51 AM - edited 2024-11-01 11:51 AM
I have no idea what you mean by "sending" device and "receiving device". From this thread I only know about "non-working device". So what's the clock frequency of your non-working device?
If it's 131 kHz, then forget HAL.