Thread: RTOS, LUTs and interrupts

  1. #1
    Registered User
    Join Date
    Jul 2008
    Posts
    12

    RTOS, LUTs and interrupts

    Using a Freescale DSP chip, I have 3 timers that grab a value out of an their own respective LUT to generate a sine wave (often with many harmonics) and then send the information out to a DAC. The system is controlled over a serial interface by a GUI (which I am am also designing).

    I send the information defining the amplitude of each of the harmonics and then generate the sine LUT's for the outputs.

    I ran into a problem where every so often when I send new data the sine LUT has some corrupted data in it. After poking around, I noticed that if I turned off the timers when I was updating the sine LUT, it worked flawlessly (other than seeing the sine wave stop updating sometimes while the timers are off).

    So clearly the problem is that I am accessing the data at the same time I am updating this. I don't know why this is. I figured that with a processor, with code running serially, this wouldn't happen.

    I was just wondering what the proper way to do this is. I figured that I could have two LUTs, update one while reading from the other and then just switching a pointer at the end. But I am slightly concerned about memory size and I feel like this complicates my communications interface.

    Anyone have any suggestions?

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Sounds like a nasty problem to solve. Unfortunately, I haven't got any good suggestions directly.

    Are you by any chance touching the LUT registers in the interrupt service routine? Maybe you need to save the LUT register settings at the start of ISR and then restore at the end?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Jul 2008
    Posts
    12
    Thanks for the response, but it is nothing like that. If that were the case, I would think that the problem could arise at anytime, but it only happens when I try to update the LUT.

    I think I will just go with swapping the arrays, that seems to work and hopefully I won't need any extra memory. . . if I do I can deal with the problem when I get there. Unless, of course, someone else comes up with a solution.

    I will be checking back. I may even be at the point where I can reasonably help OTHER people with programming problems.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > I noticed that if I turned off the timers when I was updating the sine LUT
    So this is done via the serial line (and the GUI at the other end)?

    What is the relative priority of the timers and the serial line interface?

    It seems to me that the corruption is down to missed interrupts somewhere along the way. Either the timers take too long, and you miss serial line data and end up with garbage coming in.
    Or the serial interrupt takes too long and you miss a step in the LUTs with the timers.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Jul 2008
    Posts
    12
    Salem,

    Your suggestion definitely makes sense and it is something I have explored.

    However, all I do is send the information about the wave and then generate it on chip; I send the amplitude and phase of the fundamental frequency and then the amplitude of 4 harmonics in the wave (there is other information, but it does not directly affect the problem). That being said, I have never seen the information get in incorrectly.

    What happens is that I use that data passed in to generate the harmonic LUT. It is during the generation of that LUT that the data gets messed up. . .and it is just a couple of values. The bulk of the 360 samples come out fine, but maybe 4-5 will get screwed up.

    But, again, if I stop the timer while updating the LUTs, it generates the waves perfectly. It is so bizarre.

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    These timers only read from the LUTs? No writing?

    How many places, or in what parts do you write to the LUTs?

    gg

  7. #7
    Registered User
    Join Date
    Jul 2008
    Posts
    12
    It is only written to when the serial interfaces calls the function to generate them. Intentionally, of course, I guess I could have some kind of pointer problem writing randomly, but I don't think that is it.

    If I let the program run freely, which enters the ISRs all the time, the LUT never changes. The only time it gets messed up is when I write to them while the ISRs are running.

    In an attempt to solve the problem I assigned two LUTs to each wave. I read from one and if I require an update, I update the other and then just swap the pointers at the end. This exhibits the same exact problem and can be solved in the same way by disabling the interrupts while I am updating the array.

    So even if I were accidentally writing to the array I was just trying to read, it shouldn't affect the array that it was not reading from.

    Bizarre stuff.

  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    The key clue is that masking interrupts masks the issue.
    If there's only one part of the code that ever writes, then it may be a reentrancy issue - which would explain why masking interrupts prevents it from occurring. Or perhaps the writing algorithm relies on other external data that may change on you if interrupts are running.

    What platform, environment does this code run in?

    gg

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Are your timer ISRs saving the entire machine state?
    It seems to me that you might be trashing a register used in the calculations of the interrupted function.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    Jul 2008
    Posts
    12
    Sweeet.

    I found the problem. Not exactly sure why it works or what the hell it is doing, but I am pretty sure the problem has been solved. Maybe you guys could explain it to me a little better.

    I didn't write the original code. . . my background story is that I am a hardware designer with a lot of FPGA background. By chance I ended up becoming the embedded C programmer and .Net developer for out company. I have been working with another developer's code so it gave me a starting point.

    When you two started talking about reentrancy and saving the SM it reminded me that one of the #pragma interrupt "calls" (I am not exactly sure what that line does) had a "saveall" at the end. I remember this sticking out to me because I had no idea what it meant. . .well, I guess I just don't understand pragma's all that much.

    So, I just stuck a saveall on the end of all of those "calls" that were causing the problem. Boom. Problem solved. Thanks.

    I understand that the "saveall" tells it to save more registers than it was saving before, but I guess I don't fully understand the pragma.

    Thanks for the help.

    Charlie

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You'd have to read the documentation to find out.

    Each compiler is free to implement as many #pragma's as they want, and to mean whatever they want.

    But FWIW, most compilers targetted at embedded systems tend to have a few more, since they're closer to the metal. The example of the moment being it needs an extra bit of magic to make a function capable of being called in ISR context.

    Though putting the saveall at the end of the function seems a strange place to put it though
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I think what holychicken meant wast that the added saveall went on the end of the #pragma line - which may make more sense: the ISR should save ALL registers, rather than just some, perhaps?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    That would make more sense
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed