This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

VPFE/VPSS Interrupt Routing to c64x CPU

Other Parts Discussed in Thread: TMS320DM6437, AM1808

Hi There,

I've been playing around with my newly purchased evaluation module for the tms320dm6437.  In specific I've been spending some time getting various features of the VPSS up and running.  I'm trying to get a basic video processing software block up working.  Basically what I want to do is stream video in to DDR2 using the VPFE, make some simple modification on a per pixel basis in software (eg something stupid like add some offset to the luminance of every pixel), and then use the VPBE to output my modified video to the video DAC and display it.  Obviously my final application isn't to add some offset to every pixel, but I thought it would be a good way to get the rest of the system up and running before I start implementing any real video processing algorithms.

I see that the VPFE outputs interrupts offset from VD (as well as other end of frame interrupts if you use the sub modules like the resizer etc).  As I recall the interrupt is VIDINT0/1.  On interrupt I'd like to call my routine to process the current frame.  I'm having trouble understanding how I route that VIDINT0/1 interrupt to the c64x CPU.  I skimmed the interrupt controller section of the megamodule reference guide, but it's still not clear to me how I get the cpu to respond to VPSS interrupts.  Any ideas?  Is there a PDF I should read?  Thanks!

 

Dave

  • Hopefully you're using BIOS.  Here's a wiki page on how to setup an interrupt using BIOS:

    http://wiki.davincidsp.com/index.php/Setting_up_interrupts_in_DSP_BIOS

     

  • I am actually not planning on using BIOS...  Any suggestions for doing it in plain C/by hand?  I guess what I'm missing is information how the interrupts generated from the VPSS (or any other internal peripheral for that matter) are routed to the CPU and how I go about using these signals as interrupts to the CPU.  On that wiki page I see a partial table of interrupt events and their corresponding numbers....  It looks like the BIOS tool then simply configures the masking registers appropriately.  Assuming that's right, where is the rest of that table/info on how to hand configure said registers?   Thanks,

    Dave

  • I've attached some code I wrote a while back for C6455.  A few key comments:

    vectors.asm

    • defines the vector table
    • Uses a .nocmp directive so assembler doesn't use 16-bit opcodes (needs to be a specific size)
    • Uses a ".sect vectors" which gets referenced in linker command file
    • To plug an ISR you would need to put a branch instruction in the corresponding interrupt vector
    • Note that I did it "lazy" in this code and just used a relative branch.  The "proper" way would be to push a register, move the complete address into the register, branch to that address, pop original contents during delay slots.  The "lazy" way will work as long as the table and ISR are both in the internal RAM (4 MB reach?)

    c6455.cmd

    • linker command file
    • vector table must be 1KB aligned!!!
    • RUN_START defines a symbol for use in main.c to configure ISTP register to point to the vector table
    • This was a quick reference so no external memory is defined in this file.
    • Don't assign code/data to L1P/L1D unless you have made sure that the L1 has been configured as RAM instead of cache.  The bootloader would have to do that.

    main.c

    • sets ISTP to point to vector tables
    • sets IER.NMIE
    • sets IER.INT4
    • sets GIE
    • uses "interrupt" keyword in ISR

     

    6455 Starter Project.zip
  • Hi Brad,

    Thanks for the quick reply.  While the code makes sense to me, I'm still missing the following key piece of information: how do I specify an interrupt service routine for the VPSS interrupts??  Specifically in the documentation for the VPFE there is an interrupt called VIDINT0.  How do I get the CPU to recognize that interrupt?  Where/how do I reference VIDINT0 as an interrupt that the CPU should respond to?  I see in the vectors.asm file that you've setup the maskable interrupts int4-int15.  This all makes sense to me.  What doesn't make sense to me is how I setup one of these interrupts to be sensitive to VIDINT0 (or any other peripheral interrupt for that matter).  Thanks,

     

    Dave

  • See page 200 of the datasheet.  It shows you the interrupt numbers of VIDINT0-2 (24-26).

    Oooh, just realized a key thing that's missing...  You would need to program the INTMUXn registers to map the interrupt.  So for example, if you wanted to map VIDINT0 to INT4 you would do this:

    pInterruptRegs->INTMUX1 &= ~0x7F;  // clear out field corresponding to INT4
    pInterruptRegs->INTMUX1 |= 24;  // map interrupt 24 to INT4

    For more information on the INTMUXn registers please see Chapter 7 (Interrupt Controller) of the 64x+ Megamodule Reference Guide.

  • Ahh!  Very cool!  Thank you.  I'll give that a shot tomorrow and report back on the results, but that was indeed what was missing for me.  Thanks!

    Dave

  • Anonymous
    0 Anonymous in reply to Brad Griffis

    Dear Brad,

     

    I have downloaded the file and am currently studying it.

     

    Regarding the grammar, I have read in the 643x manual that .nocmp is a "no compact" directive. Is a dot preceding the literal the syntax for all directives? And regarding

    1. .ref
    2. .sect
    3. mvkl
    4. mvkh

     

    Are 1 & 2 directives, 3 & 4 assembly instructions?


     .ref    _c_int00
     .ref _my_isr       
     
     .sect "vectors"

     .nocmp

    RESET_RST:  
         mvkl .S2 _c_int00, B0
         mvkh .S2 _c_int00, B0
         B    .S2 B0
      NOP
      NOP
      NOP
      NOP
      NOP

     

    I am completely new to assembly language. Could you provide me some links/docs on the grammar, structure and purpose of vectors.asm, so that I could write one by my own to handle interrupt request for simple applications (without BIOS)?

     

     

    Sincerely,

    Zheng

     

  • Anonymous
    0 Anonymous in reply to Brad Griffis

    Dear Brad,

     

    I am studying this example you provide. I notice that in vectors.asm you map INT4 to my_isr() like this:

     

    INT4:

                            b          _my_isr

                            NOP

                            NOP

                            NOP

                            NOP

                            NOP

                            NOP

                            NOP

              

                 

                 

                  

                   

             

     

    You are all using “NOP”s. But according to SPRU732g, page 5-7, Fig. 5-2 Interrupt Service Fetch Packet, there needs to be an “NOP 5” after interrupt return pointer instruction (B IRP). The reason for the insertion of “NOP 5”, according to this document, was that

     

    “there are five delay slots between the execution of the branch and execution of the target code”.

     

    I have a question:

     

    If my understanding is correct, the “b” preceding “_my_isr” here is also a branching in the sense that it “jump”s to the my_isr() function.

    1.    There is no “NOP 5” in your program, is it because of the difference between my_isr(), which is a user written routine, and IRP, which is an internal CPU instruction?

    2.    Or is it because that there are 7 NOPs after “b   _my_isr”, which is more than the “five delay slots”, so that there is no need for “NOP 5”?

     

     

    Sincerely,

    Zheng

  • Zheng Zhao said:

     

    I am completely new to assembly language. Could you provide me some links/docs on the grammar, structure and purpose of vectors.asm, so that I could write one by my own to handle interrupt request for simple applications (without BIOS)?

     

    Hi Zheng,

    There are a couple documents you should reference:

    Brad

     

  • Zheng Zhao said:
    I am studying this example you provide. I notice that in vectors.asm you map INT4 to my_isr() like this:
     
    INT4:
                            b          _my_isr
                            NOP
                            NOP
                            NOP
                            NOP
                            NOP
                            NOP
                            NOP

    I should mention that the code above was just a quick hack to get things working.  Although it is functionally correct it is limited from the perspective that it is using a relative branch.  This limits the placement of your ISR relative to the vector table.  The "proper" way to do this is with an absolute branch which is a little more complicated because it requires a register.  Here's how it should look:

                        stw b0,*b15--[2]        ; temp save b0 on stack
                        mvkl _my_isr,b0        ; load destination address to b0
                        mvkh _my_isr,b0
                        b b0                    ; start branch to destination
                        ldw *++b15[2],b0        ; restore b0 register
                        nop 2                   ; fill 2 of b0 restore delay slots
                        nop                     ; fill delay slot, pad packet
                        nop                     ; fill delay slot, pad packet

    Zheng Zhao said:
    1.    There is no “NOP 5” in your program, is it because of the difference between my_isr(), which is a user written routine, and IRP, which is an internal CPU instruction?

    After executing a branch instruction the CPU will execute the following 5 instructions.  So if you put a "NOP 5" after the branch instruction it will execute 5 NOPs.  Having 5 separate NOP instructions accomplishes the same thing.  In my case I have 7 total NOP instructions.  Only 5 would actually be executed during an ISR.  The other 2 are there because each interrupt service fetch packet is composed of 8 instructions.

    Zheng Zhao said:
    2.    Or is it because that there are 7 NOPs after “b   _my_isr”, which is more than the “five delay slots”, so that there is no need for “NOP 5”?

    Correct.

  • Anonymous
    0 Anonymous in reply to Brad Griffis

    Dear Brad,

    These documents are exactly what I am looking for and explained clearly what those directives are. Thanks very much.

     

    Zheng

  • Anonymous
    0 Anonymous in reply to Brad Griffis

    Dear Brad,

    I need some time to study your code, thanks very much.

     

    Zheng

     

  • Anonymous
    0 Anonymous in reply to Brad Griffis

    Brad,

    I am now studying AM1808 processor and would like to find a way to configure interrupts in the "hard" manner as you did here. However, a Q&A between a forum user and TI employee Mariana was:

     

    Prodigy50 Points

    Hi Mariana,

    Is there any example code using the ARM interrupts without Linux? I need to implement interrupts on "bare" omap-l137 

     

     

    Mastermind23315 Points

    Not really. Our software offering for the ARM is Linux dependent.

    - Mariana

     

    Are you aware of any sample code on AM1808 that is not Linux dependent, like you did here?

     

     

    Zheng

     

     

  • Anonymous
    0 Anonymous in reply to Brad Griffis

    Brad,

    I have downloaded it, thanks.

     

    Zheng