Please note as of Wednesday, August 15th, 2018 this wiki has been set to read only. If you are a TI Employee and require Edit ability please contact x0211426 from the company directory.

Setting up interrupts in DSP BIOS

From Texas Instruments Wiki
Jump to: navigation, search

Introduction

This article applies to 64x+ and 674x DSP cores using the DSP/BIOS RTOS. It explains how to configure hardware interrupts in the DSP/BIOS configuration GUI.

Key Steps

On 64x+/674x cores there are 12 maskable interrupts, INT4-INT15. Depending on what timer you use for your system tick, BIOS will use either HWI_INT14 or HWI_INT15, whichever one has "CLK_F_isr" already populated. You can choose any of the remaining ones as your interrupt. Let's say you choose HWI_INT5...

  • Go to Scheduling -> HWI
  • Right-click on selected interrupt (e.g. HWI_INT5) and select Properties.
  • Enter the assembly label of your ISR. Note: if your ISR is written in C then it needs to have a leading underscore.

BIOS Interrupt1.jpg

  • Fill in the "interrupt selection number" with the appropriate number as listed in the datasheet. For example on a TMS320C6455 if you wanted a McBSP1 receive interrupt you would choose 42 as your interrupt selection number.

BIOS Interrupt2.jpg

  • Go to the Dispatcher tab and check the "Use dispatcher" box. Your ISR should be a normal C function. Do not use the interrupt keyword in addition!
  • If you want to allow other interrupts to pre-empt your interrupt leave "interrupt mask" as "self". If you don't want interrupts to nest then choose "all".

BIOS Interrupt3.jpg

  • In your application you need to enable the chosen interrupt in the IER. Normally this is done during main().
#include <c64.h>
C64_enableIER (C64_EINT5);
  • If you're enabling multiple interrupts then OR the masks together, e.g. C64_EINT5 | C64_EINT6.

Steps performed for you by BIOS

  • BIOS creates an interrupt vector table for you.
  • BIOS maps the corresponding interrupt event (0-127) to the selected CPU interrupt (4-15) by configuring the INTMUXn register for you.
  • When you return from main() and BIOS starts its scheduler it will automatically enable global interrupts for you.
  • BIOS handles properly nesting interrupts for you unless of course you choose the interrupt mask as "all" in which case it disables nesting (hardware default).

Troubleshooting

Watch out for run-time allocation!

BIOS allows you to setup interrupts statically in the tcf (i.e. at compile time) or dynamically in your code using HWI_dispatchPlug API (i.e. at run-time). If there is code in the system dynamically allocating interrupts, e.g. NDK or EDMA LLD, then you might not realize that your interrupt configuration is being clobbered at run-time!

Discovering this issue. Rather than combing through all possible code, the best way to see if you're being bitten by this issue is to look at a few registers. For a given interrupt, here's where to look:

INT4:  0x0180_0104 INTMUX1[6:0]
INT5:  0x0180_0104 INTMUX1[14:8]
INT6:  0x0180_0104 INTMUX1[22:16]
INT7:  0x0180_0104 INTMUX1[20:24]
INT8:  0x0180_0108 INTMUX2[6:0]
INT9:  0x0180_0108 INTMUX2[14:8]
INT10:  0x0180_0108 INTMUX2[22:16]
INT11:  0x0180_0108 INTMUX2[20:24]
INT12:  0x0180_010C INTMUX3[6:0]
INT13:  0x0180_010C INTMUX3[14:8]
INT14:  0x0180_010C INTMUX3[22:16]
INT15:  0x0180_010C INTMUX3[20:24]

Whatever number you filled in earlier for the "interrupt selection number" should show up in the corresponding field above (in hex). If that number is not present at run-time that indicates that HWI_dispatchPlug has been called and has overwritten the configuration you specfied in the tcf. The easiest way to solve the issue is to choose another interrupt. Alternatively you can look for the "offending" source code and change it to use a different interrupt.

Why do I get one interrupt and then no more?

You may be having this issue without even realizing it. If your breakpoint is not set in your ISR before you run your code then you may hit the ISR once (and only once) without ever realizing it.

This issue generally occurs in the case of a shared interrupt (e.g. EDMA, GPIO bank interrupt, etc.). For shared interrupts you generally must clear a bit in the peripheral register after having serviced the corresponding event. See the specific peripheral guide for further details.