I want to implement an interrupt vector table with using Nim only.
My code:
proc main() {. importc .}
const weakAttr = "__attribute__((weak)) $# $#$#"
proc ResetHandler() {. exportc, codegenDecl: weakAttr .} = main()
proc NMIHandler() {. exportc, codegenDecl: weakAttr .} = discard
proc HardFaultHandler() {. exportc, codegenDecl: weakAttr .} = discard
...
let isrVector {. exportc: "_isrVector" .} = [
ResetHandler,
NMIHandler,
HardFaultHandler,
...
]
expected array in ROM:
N_LIB_PRIVATE NIM_CONST tyArray__oXFh4MvEDAk4hEbFQSH7yQ _isrVector = {
ResetHandler,
NMIHandler,
HardFaultHandler
...
};
__attribute__((weak)) void ResetHandler(void) { main(); }
__attribute__((weak)) void NMIHandler(void) { }
__attribute__((weak)) void HardFaultHandler(void) { }
...
but got a runtime initialization of the array in RAM:
N_LIB_PRIVATE tyArray__eT4n0wdQ8ecm15lH5Od2Ag _isrVector;
__attribute__((weak)) void ResetHandler(void) { main(); }
__attribute__((weak)) void NMIHandler(void) { }
__attribute__((weak)) void HardFaultHandler(void) { }
...
N_LIB_PRIVATE N_NIMCALL(void, atmstm32f303ccatsstartupdotnim__startupInit000)(void) {
_isrVector[0] = ResetHandler;
_isrVector[1] = NMIHandler;
_isrVector[2] = HardFaultHandler;
...
}
I tried to add __attribute__((used)) attribute, but got error:
Error: cannot attach a custom pragma to 'isrVector'
const isrVector {. exportc: "_isrVector", codegenDecl: "__attribute__((used)) $# $#" .} = [
ResetHandler,
NMIHandler,
HardFaultHandler,
...
]
Workaound:
proc main() {. importc .}
const weakAttr = "__attribute__((weak)) $# $#$#"
proc ResetHandler() {. exportc, codegenDecl: weakAttr .} = main()
proc NMIHandler() {. exportc, codegenDecl: weakAttr .} = discard
proc HardFaultHandler() {. exportc, codegenDecl: weakAttr .} = discard
const isrVector {. exportc: "_isrVector" .} = [
ResetHandler,
NMIHandler,
HardFaultHandler
]
{.push checks: off.}
var dummyRuntimeIndex {.nodecl.} = 0
{.emit: ["/*", isrVector[dummyRuntimeIndex], "*/"].}
{.pop.}
Thanks. It works!
Another issue. Is there a way to avoid repeating pragmas without writting macros? Something like:
{. exportc, codegenDecl: "__attribute__((weak)) $# $#$#" .}:
proc ResetHandler() = main()
proc NMIHandler() = discard
proc HardFaultHandler() = discard
You might be able to use the push and pop pragma, as such:
{.push exportc, codegenDecl: "__attribute__((weak)) $# $#$#" .}
proc ResetHandler() = main()
proc NMIHandler() = discard
proc HardFaultHandler() = discard
{.pop.}