2022-02-09 11:11 AM
Another day, another bug....
I'm trying to use ADC3 with BDMA on H753.
Started from some cube-generated code that assigned BDMA channel 0 to ADC3.
Allocated memory in SRAM4. Added interrupt handler for BDMA_Channel0 and ADC3.
When I start the ADC3, I hit the default interrupt handler - as if the proper handler is not defined.
ICSR = 0x891 this means the active interrupt is 0x91.
0x91 - 16 = 129 which is exactly BDMA_Channel0_IRQn.
And there's the handler for it. But this handler is not hit. Why??
DMA_HandleTypeDef hdma_adc3;
ADC_HandleTypeDef hadc3;
void ADC3_IRQHandler(void)
{
HAL_ADC_IRQHandler(&hadc3);
}
void BDMA_Channel0_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_adc3);
}
I've checked the listing and the vector table, the vector indeed points to my BDMA_Channel0_IRQHandler.
VTOR looks correct (systick works, and the default handler is there as well).
Same behavior when the code is in internal flash or AXI RAM. Caches NOT enabled.
So how comes that the default handler is called?
Is there an example of ADC3 in DMA mode (BDMA) for STM32H7x3?
Solved! Go to Solution.
2022-02-11 10:39 AM
> Have not increased the table alignment yet.
Do it.
Apparently, NVIC is not *adding*, but *ORing* the ISR's offset (ISR number << 2) to VTOR.
JW
2022-02-09 01:46 PM
> I've checked the listing and the vector table, the vector indeed points to my
BDMA_Channel0_IRQHandler.
Show.
JW
2022-02-09 03:01 PM
Verify entry in vector table points to a different location than the default handler.
If you're using C++, make sure the handler is declared as extern "C".
If you have LTO enabled, disable it.
2022-02-10 06:46 AM
@Community member
I've added some prints below.
Output:
VTOR=80E0200
intnum= 129 vec=80EA575, handler=0x80ea575
void Test_ADC3()
{
printf("VTOR=%X\n", SCB->VTOR);
printf("intnum= %u vec=%X, handler=%p\n", BDMA_Channel0_IRQn,
((uint32_t*)SCB->VTOR)[BDMA_Channel0_IRQn + 16],
(void*)BDMA_Channel0_IRQHandler );
...............
unsigned memsize = hadc3.Init.NbrOfConversion * sizeof(uint16_t);
f_adc_cnvrt_complete = 0;
HAL_StatusTypeDef st = HAL_ADC_Start_DMA(&hadc3, (void*)ADC3_BUF_BASE_, memsize);
if (0 != st ) {
__BKPT(14);
}
.............
}
Here it lands on the default handler, R1= 0x891
And snippet from the .list file
080ea574 <BDMA_Channel0_IRQHandler>:
{
80ea574: b508 push {r3, lr}
HAL_DMA_IRQHandler(&hdma_adc3);
80ea576: 4802 ldr r0, [pc, #8] ; (80ea580 <BDMA_Channel0_IRQHandler+0xc>)
80ea578: f7fe fae2 bl 80e8b40 <HAL_DMA_IRQHandler>
}
80ea57c: bd08 pop {r3, pc}
80ea57e: bf00 nop
80ea580: 240002cc .word 0x240002cc
2022-02-10 07:27 AM
Try to generate *separate* handlers for every item in the table.
Also, try to align table to higher power of 2 (yes I know PM0253 requires only bits 0..8 to be zero, try more).
JW
2022-02-10 09:03 PM
@Community member Jan, with separate handlers I get a weird result .. simply cannot believe my eyes.
This appears to be vector #1 (so I've mis-interpreted the ICSR; no need to subtract 16, the low bits of 0x91 b'10001 mean 17 ?)
Vector 1 is PVD_AVD_IRQn - interrupt from programmable voltage detector or analog voltage detector (RM0433, 5.5.3-5.5.4).
The RM says the interrupt must be enabled in EXTI and AVD/PVD must be enabled in PWR_CR1. When the interrupt is hit RWR_CR1 = 0xF000C100 so bits AVDEN and PVDE are both 0. (RM0433, 5.8.1)
I'm still checking if there is some error in my setup.
Have not increased the table alignment yet.
The interrupt remains active, I don't know how to block it. NVIC_DisableIRQ(PVD_AVD_IRQn) does not help.
Regards,
P.
2022-02-11 10:39 AM
> Have not increased the table alignment yet.
Do it.
Apparently, NVIC is not *adding*, but *ORing* the ISR's offset (ISR number << 2) to VTOR.
JW
2022-02-11 11:48 AM
> VTOR=80E0200
The alignment is not correct for this device. PM0253 section "2.4.4 Vector table":
The silicon vendor must configure the top range value, which is dependent on the number of interrupts implemented. The minimum alignment is 32 words, enough for up to 16 interrupts. For more interrupts, adjust the alignment by rounding up to the next power of two. For example, if the user requires 21 interrupts, the alignment must be on a 64-word boundary because the required table size is 37 words, and the next power of two is 64, see Vector table offset register on page 197.
According to RM0433 section "19.1.2 Interrupt and exception vectors" this device has 150 interrupts. Therefore the size of vector table is 16+150=166 words. The next power of two is 256 and therefore the VTOR for this device must be aligned to 1024 bytes.
In this case the closest correct addresses are 0x080E0000 and 0x080E0400.
2022-02-11 12:30 PM
The 0x91 is 0b1001'0001, which after multiplication by 4 (left shift by 2) becomes 0b10'0100'0100. Now, because the current VTOR address ends with 0b10'0000'0000, after OR operation the bit #9 is effectively ignored. That means the device actually fetches an address, for which the offset is lowered by 2^9=512 bytes or 128 words. That's why instead of fetching a vector 145 (0x91) it fetches 145-128=17, which translates (by subtracting 16) to 129-128=1 for interrupt numbers.
2022-02-12 12:04 AM
@Community member @Piranha Thank you so much. The PM says bits 0-8 so I thought 0x200 alignment is enough.
Jan's reply is earlier so he takes the best answer.