Barring a few teething problems the proof of concept TX code is written and working so I’m now concentrating on the RX code and have hit a snag where you cannot intercept/replace the usart interrupt vectors defined in usart_f1.c without editing the file and removing the definition(s) for the usart you want to control.
The Maple docs said somewhere that they should be made __weak so they can be replaced without having to hack the core files but this never happened and I have no real idea how to go about this.
Just preceding the usart_f1.c definition with __weak works fine as long as I write interrupt code to deal with it but if you don’t have your own interrupt code I would have expected/hoped the original definition would prevail but it does not and the MCU locks up.
/*
* Interrupt handlers.
*/
void __irq_usart1(void) {
usart_irq(&usart1_rb, &usart1_wb, USART1_BASE);
}
__weak void __irq_usart2(void) {
usart_irq(&usart2_rb, &usart2_wb, USART2_BASE);
}
Barring a few teething problems the proof of concept TX code is written and working so I’m now concentrating on the RX code and have hit a snag where you cannot intercept/replace the usart interrupt vectors defined in usart_f1.c without editing the file and removing the definition(s) for the usart you want to control.
The Maple docs said somewhere that they should be made __weak so they can be replaced without having to hack the core files but this never happened and I have no real idea how to go about this.
Just preceding the usart_f1.c definition with __weak works fine as long as I write interrupt code to deal with it but if you don’t have your own interrupt code I would have expected/hoped the original definition would prevail but it does not and the MCU locks up.
/*
* Interrupt handlers.
*/
void __irq_usart1(void) {
usart_irq(&usart1_rb, &usart1_wb, USART1_BASE);
}
__weak void __irq_usart2(void) {
usart_irq(&usart2_rb, &usart2_wb, USART2_BASE);
}
Do you need to completely replace the USART irq handler, or you just need to add to the handler?
in the second case, perhaps you could modify the core to allow it to attach an additional function to be called before or after the core handler, similar to the DMA interrupts, where there is a handler that will do a few things, and then called a user defined handler if it has been attached.
Ideally I want to replace the default handler but using a hook could be an option as long as the default IRQ code can be told to process/ignore depending on a hook return code.
For the first case, I would have thought __weak should work, but since the symbols (__irq_usart1, etc) are already declared weak in the interrupt table, perhaps that makes the __weak not work fine in the function?
__weak works fine as long as I define IRQ handlers but if I don’t define one I would expect the default to be used instead but it seems the default one is not linked so any code that uses Serial just locks up.
There was another way to declare those symbols as weak, which I applied last year for something (don’t fully remember what was it for, but i think was related to PIN_MAP in ram, which we resolved a different way), you can see in the history of that file how it was using weakref.
This is all getting a bit to advanced for my C++ skills as despite reading here I’m not the wiser what the difference is between weak & weakref.
You can test to replace that file with the version that used weakrefs, and see if in that case the __weak parameter in the function works as expected.
Will give it a try and report back.
EDIT:
I was checking when and why we tested weakrefs. I din’t read the whole story, but it had to do with some errors when -Wall was removed from the linker parameters.
In one of the posts, Rick linked to this file:
https://github.com/leaflabs/libmaple/bl … rrupts.txt
Which contains this paragraph:
IMPORTANT: the function you define MUST HAVE C LINKAGE. C++ name
mangling will confuse the linker, and it won’t find your function. So
if you’re writing your IRQ handler in a C++ file, you need to define
it like this:
extern “C” void __irq_sdio(void) {
// etc.
}
Maybe I’m doing it wrong then as I have a
extern "C"
{
void __irq_usart2(void);
}
You can test to replace that file with the version that used weakrefs, and see if in that case the __weak parameter in the function works as expected.
Will give it a try and report back.
Changing the .set to .weakref for the usart handlers in the isrs.S file and adding __weak to the interrupt handlers in usart_f1.c mean I seem to be able to intercept the default IRQ within code and if I don’t intercept then the original code still works.
Is this something worth considering for a core change? Subject to more thorough testing.
You can test to replace that file with the version that used weakrefs, and see if in that case the __weak parameter in the function works as expected.
Will give it a try and report back.
Changing the .set to .weakref for the usart handlers in the isrs.S file and adding __weak to the interrupt handlers in usart_f1.c mean I seem to be able to intercept the default IRQ within code and if I don’t intercept then the original code still works.
Is this something worth considering for a core change? Subject to more thorough testing.
You can test to replace that file with the version that used weakrefs, and see if in that case the __weak parameter in the function works as expected.
Will give it a try and report back.
Changing the .set to .weakref for the usart handlers in the isrs.S file and adding __weak to the interrupt handlers in usart_f1.c mean I seem to be able to intercept the default IRQ within code and if I don’t intercept then the original code still works.
Is this something worth considering for a core change? Subject to more thorough testing.
But we’d need to make very sure it doesnt break something ![]()
But we’d need to make very sure it doesnt break something ![]()
I’m not suggesting extensive testing, but we have been caught in the past by changing things in the past, which had unintended consequences.
But we’d need to make very sure it doesnt break something ![]()
This is the version I did
.weak __exc_nmi
.globl __exc_nmi
.weakref __exc_nmi, __default_handler
But we’d need to make very sure it doesnt break something ![]()
But we’d need to make very sure it doesnt break something ![]()
I’m not actually using it, I’m using the normal core, but seems to work for the problem Riva was dealing with.
Are you using it for all the irq handlers or in which cases?
I was active here in the BobC days andvBobC and I had a number of off-line conversations about C++ and the issues with the way Arduino is architected.
At Riva has a workaround, I would suggest that a rather detailed summary of that success be put into the WiKi and that the core be left as-is. Arduino will never be as flexible as pure C++ and most users simply are happy with Arduino for its automatic prototyping and ease of use. Most of us know that Arduino has limitations. I believe the safer approach is to document how to circumvent limitations and avoid massive engineering rework in the core.
Ray
