IRQ not firing?

On a couple of my old projects I manually reimplemented the sound system from pokittolib, however this doesn’t work anymore. I’m not sure if I missed something or if there are other factors in play.

I’m using the following code to set up the timer, but it seems to never actually run the audioTimer function. Can anyone see something wrong with it at all?

// timer init stolen directly from Pokittolib
void initTimer(uint32_t sampleRate){
     /* Initialize 32-bit timer 0 clock */
	Chip_TIMER_Init(LPC_TIMER32_0);
    /* Timer rate is system clock rate */
	int timerFreq = Chip_Clock_GetSystemClockRate();
	/* Timer setup for match and interrupt at TICKRATE_HZ */
	Chip_TIMER_Reset(LPC_TIMER32_0);
	/* Enable both timers to generate interrupts when time matches */
	Chip_TIMER_MatchEnableInt(LPC_TIMER32_0, 1);
    /* Setup 32-bit timer's duration (32-bit match time) */
	Chip_TIMER_SetMatch(LPC_TIMER32_0, 1, (timerFreq / POK_AUD_FREQ));
	/* Setup both timers to restart when match occurs */
	Chip_TIMER_ResetOnMatchEnable(LPC_TIMER32_0, 1);
	/* Start both timers */
	Chip_TIMER_Enable(LPC_TIMER32_0);
	/* Clear both timers of any pending interrupts */
    #define MY_TIMER_32_0_IRQn 18
	NVIC_ClearPendingIRQ((IRQn_Type)MY_TIMER_32_0_IRQn);
    /* Redirect IRQ vector - Jonne*/
    NVIC_SetVector((IRQn_Type)MY_TIMER_32_0_IRQn, (uint32_t)&audioTimer);
	/* Enable both timer interrupts */
	NVIC_EnableIRQ((IRQn_Type)MY_TIMER_32_0_IRQn);
}

extern “C” needed? Name mangling issue possibly

Name mangling should only be an issue if the linker is involved.

Assuming SetVector is the call responsible for setting the function to be called by the interrupt, name mangling shouldn’t be a problem because it’s the address being used here rather than the name. (Function names are only used during the linking phase, they are eliminated by the time the final binary is compiled.)

Even then, if the linker is part of the GCC toolchain, I would have expected it to be aware of the name mangling protocol in use by GCC’s C++ compiler. Name mangling is more of an issue when trying to mix code that’s been compiled with different compilers that use different name mangling protocols.

Not only then. I have previously found that name mangling can cause a very insidious problem:

There are empty weak definitions of the same C functions within the startup files.

My own functions were C++ and mangled. Everything compiled fine but the interrupt went to the empty weak function. It took me a long time initially to catch that

Point taken, though that’s as much as issue with weak symbols as it is an issue with name mangling.
Weak symbols are non-standard and not portable, and not used as much outside of embedded systems.

At any rate, my point was more that it seems that NVIC_SetVector is supposed to be a function that sets the function to be called at runtime rather than being set at compile time, thus audioTimer's name should be irrelevant because only its address is being used. Likewise if initTimer is not some special name intended to overwrite a weak symbol and is being called within the main program then only its address should matter.

Also the fact that this code used to work in the past and the code itself hasn’t changed implies some change in the PokittoLib might be causing the problem.


@spinal

Have you tried compiling it with a version of the PokittoLib from around the time when you first wrote the code?

And just to clarify, are you actually trying to compile your old projects or have you taken the old code and placed it in a new project?

The former is more likely to suggest a library change, the latter could mean that there’s something about the way it’s being used that’s causing issues. E.g. initTimer itself might not actually be being called for some reason. It may be worth putting in some serial prints to make sure the function is run from start to finis.

I have tried both, initially I just used the code in my new project, it failed. The I simply recompiled two previous projects that used the code (FM radio and Joe) both are silent. I don’t have and old Pokittolib version anywhere to try that, but they both worked fine when I made them.

1 Like

That’s what git is for.

The entire history of the PokittoLib is right here:

Click the <> symbol and you can view and download the library’s state at any point in its commit history.

If you look at the date you created the original projects you can try something from before that date to see if it works. If you find one that works, that would prove it’s a change in the PokittoLib that’s caused the problem, after which it’s a matter of stepping forward through time to locate the point at which things broke.

(Though rather than stepping linearly, it’s more efficient to do a ‘binary search’: leap forward, if that works go forward more, if it doesn’t then go back - repeat until the culprit is found.)

If the code for Joe and/or FM Radio is publicly available and someone has the time (and a working build environment) then perhaps they could lend a hand.

1 Like

Starting at #142 (d410a5372c), as it’s slightly before any mention of adopting libaudio officially. That one works fine with fmradio.

Next to test #143 (f2ac11659f) - 25 oct 2020…

[edit] nothing. It’s the differences from adding libaudio (or something else that happened at that time) that have broken it.

1 Like

Is perhaps libaudio using the exact same timer, and wiping out the setup I use?

That seems plausible.

It’s definitely got code for taking over the same interrupt:

The question is: is it being automatically used by PokittoLib somehow?


At what point is your sound initialisation code being called?

I also noticed this line:

So if that’s occurring after your sound initialisation code (granted, it’s not likely, but I thought I’d double-check anyway) then it could explain the problem.

Since LibAudio became PokittoLib’s sound backend, PokittoSound.cpp contains the following:
Audio::Sink<NUM_CHANNELS, POK_AUD_FREQ> audioSink;

With that, an audio sink is created and it will install its own IRQ listener when you call Core::update().

As you can see here:

    void init(){
        NVIC_SetVector((IRQn_Type)TIMER_32_0_IRQn, (uint32_t)IRQ);
        if(this->wasInit)
            return;
        this->wasInit = true;

It will set the interrupt regardless of whether it has been previously initialized or not. This was necessary because pre-LibAudio PokittoSound could’ve been initialized afterwards, stealing the interrupt handler.

Now, it’s probably safe to move that line down, like this:

    void init(){
        if(this->wasInit)
            return;
        this->wasInit = true;
        NVIC_SetVector((IRQn_Type)TIMER_32_0_IRQn, (uint32_t)IRQ);

Another option would be to make use of the asm-optimized LibAudio IRQ handler and write your own Source that does what you need. Have a look at the ByteBeatSource for an example, it isn’t very complicated.

1 Like

this

    public:
        void init(){
            if(this->wasInit)
                return;
            this->wasInit = true;
            NVIC_SetVector((IRQn_Type)TIMER_32_0_IRQn, (uint32_t)IRQ);

makes no difference. But

    public:
        void init(){
			return; // <-------- this
			if(this->wasInit)
                return;
            this->wasInit = true;
            NVIC_SetVector((IRQn_Type)TIMER_32_0_IRQn, (uint32_t)IRQ);

Perhaps this->wasInit = true; isnt working?

You just need to make sure init is called before you setup your own handler.
Try calling Core::update() after begin(), then you can call NVIC_SetVector.

1 Like

Perfect, I assume writeDAC() is now mia…

Missing In Action?

yeah, can’t find it :-P. I do remember even though I was using my own timer etc. I still needed to define PROJ_ENABLE_SOUND, so I guess there was something else I missed for setting up audio.

[edit] So far, I’m setting up the timer, enabling the DAC, switching on the amp, and using the following to write the DAC…

inline void writeDAC(unsigned char out) {
    volatile unsigned char* P1 = (unsigned char*)(0xa0000020);
    volatile unsigned char* P2 = (unsigned char*)(0xa0000040);
    P1[28] = out & 1; out >>= 1;
    P1[29] = out & 1; out >>= 1;
    P1[30] = out & 1; out >>= 1;
    P1[31] = out & 1; out >>= 1;
    P2[20] = out & 1; out >>= 1;
    P2[21] = out & 1; out >>= 1;
    P2[22] = out & 1; out >>= 1;
    P2[23] = out;
}

But I’m no hearing anything.

You probably don’t need to do any of that, other than redirect the IRQ since LibAudio already does it. Are you sure the volume isn’t 0?

Volume is max.
On the current Joe project I can hear the squeaking of the SD reads and a ticking noise. On the FMRadio project it seems to work, so at this point it must be something about my project, rather than the libs.

[edit] It seems that the function that I use to mix the audio in ‘Joe’, does not work at all in ‘Joe2’… weird. But I now have sound :slight_smile: thanks guys!