PDA

View Full Version : Default IRQ



Mike_FN
Aug 5th, 2016, 06:40 AM
Does anyone know how to set a default interrupt function on Tricore?
The vector table lsl looks like this:
section_layout :vtc:linear
{
"_lc_u_int_tab_tc0" = (INTTAB0);
"_lc_u_int_tab" = "_lc_u_int_tab_tc0"; /* common cstart interface for first or single core */

// interrupt vector tables
group int_tab_tc0 (ordered)
{
group (run_addr=(INTTAB0)+0x0000) select ".text.inttab0.intvec.000";
group (run_addr=(INTTAB0)+0x0020) select ".text.inttab0.intvec.001";
group (run_addr=(INTTAB0)+0x0040) select ".text.inttab0.intvec.002";
...
group (run_addr=(INTTAB0)+0x07f8) select ".text.inttab0.intvec8.0ff";
}
At the moment I get instruction traps and would rather a dedicated undefined interrupt function runs.
.text.inttab0.intvec.xxx is only defined for certain IRQs. Using fill="_my_undefined_irq" didnt work, probably because it need to be a jump instruction?
On the C side IRQ functions are being added with "IFX_INTERRUPT(my_irq, 0, my_priority);".

James.Donahue
Aug 8th, 2016, 06:11 AM
Not totally sure what you are looking to do here, either have all interrupts go to the same location or fill in all vector locations with your default handler.

If you want a single interrupt handler for all interrupts instead of using a vector table you need to mask out the (Pending Interrupt Priority Number) PIPN in the BIV register. If you set BIV.b0 = 0 for 32 byte Vector Spacing, then set bits 5-12 to 1s all interrupts will go to the same handler. This is because Infineon uses an OR operation instead of a ADD operation to get the handler address. Thus if you set the BIV to 0x80003FE0 and place your interrupt handler at this address, all interrupts will go to that handler. Search user manual for "Use Case Example Interrupt Handler". Unless you are using assembly to handle the difference between a regular function and an interrupt handler you still need to tell the compiler its an interrupt handler. This should work with Tasking on a single core device, but I would have to try it to be 100% sure.
void __interrupt(0) my_handler (void)
{


}

If you want to stick with vectored interrupts I think you need define a handler for every enabled priority in the Interrupt Router and have it call your default handler.

Mike_FN
Aug 8th, 2016, 08:12 AM
Hi James thanks for the reply,
What I want to do is catch at runtime interrupts that are configured to execute but have no function specified in the table,
by specifying a default function where .text.inttab0.intvec.xxx does not exist in the lsl, or somehow specifying it for all vectors but not overriding any existing "IFX_INTERRUPT(my_irq, 0, my_priority) in the C.

TASKING.hp.glas
Aug 9th, 2016, 07:35 AM
Hi James thanks for the reply,
What I want to do is catch at runtime interrupts that are configured to execute but have no function specified in the table,
by specifying a default function where .text.inttab0.intvec.xxx does not exist in the lsl, or somehow specifying it for all vectors but not overriding any existing "IFX_INTERRUPT(my_irq, 0, my_priority) in the C.

Hi Mike,

I may have a solution for you which makes use of the `vector_table` LSL keyword. For this keyword to properly work it needs support from the compiler, which currently does not exist. The compiler needs publish some special symbols that the locator can use to weave together vector table entries by means of a vector template. So you can make it work if you know how to publish those labels yourself, and preferably from C level.

I have attached a sample case, which I’ll walk through step-by-step. There’s always a chance that I forget to mention some vital stuff, so feel free to ask if something needs clarifying.

Installing the example can be done as follows:

1. select ‘file | import’ MENU
2. select ‘existing projects into workspace’ IMPORT SOURCE
3. select ‘select archive file’ RADIOBUTTON
4. click ‘Browse…’ BUTTON and proceed to import mike.zip

Following the import, note that the linker Miscellaneous options contains `-DDEBUG` as an additional command line option. Also note that in `mike.lsl` I do a conditional check on this define. It then conditionally includes either `tc27xc.lsl` or `debug_tc27xc.lsl`. The former is a system LSL file. The rule is never to edit those because there should be no reason to. The latter is a copy of that same system file, because in fact we _have_ reason to change it. Doing it this way though, makes sure the system LSL remains unscathed. So once you remove the `-DDEBUG` command line option you rely on the official vector table again, which you should do prior to release.

The weak in `debug_tc27xc.lsl` is that it doesn’t include `inttab0.lsl`. Instead, at the bottom, it used the following snippet of LSL:



2513

What this does is a couple of things. It tells the locator the vector table consists of 256 vectors beginning at `INTTAB0`. It further tells it that each entry has a size of 32 bytes. It then explains that when it populates vector entries it must make use of a template section called `.vtctext.vector`, which we need to provide ourselves. I’ve code this piece of assembly in `vector.asm`, also part of the project. Note that the template refers to a label called `_lc_vector_target` and this is where the publishing comes into play.

In `main.c` note that I’m coding two interrupt functions. One I call `default_handler()` and the other is a `regular_handler()`. The first I want to use to fill all default entries in the vector table for as long as no interrupt service routine is being coded explicitly. The second overloads the default handler, as will any other interrupt service routine that’s being coded. To make all of this work, a couple of things need to be done. First note the `fill` keyword in the LSL snippet. Next note the `_Pragma(“alias …”)` language extensions that publish labels `_vector_0` and `_vector_1`, effectively `default_handler` and `general_handler`. Note how the naming convention for these match the `vector_prefix` qualifier in LSL. Using these pieces of information the linker can now start weaving the vector table. The mapfile will use the same naming convention for the vector entries as was used for the published symbols.

As a test you can download the program image in the simulator and inspect address `0xa00f0000`. All vector entries jump to `default_handler()`, with the exception of vector table entry 1 that jumps to `regular_handler()`.

To wrap things up, note that the LSL snippet uses the `no_inline` keyword. As soon as you drop it, the linker will try to inline the function body of your interrupt handler for as long as it’s smaller than or equal to 32 bytes, or use the jump template in case of it being larger than 32 bytes.

Let me know how this works out. I did note use the IFX_INTERRUPT macro but I’ll assume you know how to recode it to include _Pragma(“alias …”), and establish the required publishing.

Best regards,

Henk-Piet Glas
Technical Product Specialist

Mike_FN
Aug 11th, 2016, 08:17 AM
Hi, I have now gotten this completely working in my project and its brilliant!
I thought about the __vector_table and fill but wouldn't have had time for the asm. This should really be the default, as for XC processors. Especially since the previous default setup fills gaps and unused vectors in the vector table with random stuff, which could then get executed due to miss config.

Just one question is there a cunning way to use a #define inside the _Pragma("") for the number. Since the vector number is used three times and needs to be unique it would be cleaner. E.g. _Pragma("alias _vector_" ##MY_FUNC_PRIORITY "=my_func") ?
Many thanks

TASKING.hp.glas
Aug 11th, 2016, 09:51 AM
Hi, I have now gotten this completely working in my project and its brilliant!
I thought about the __vector_table and fill but wouldn't have had time for the asm. This should really be the default, as for XC processors. Especially since the previous default setup fills gaps and unused vectors in the vector table with random stuff, which could then get executed due to miss config.

Just one question is there a cunning way to use a #define inside the _Pragma("") for the number. Since the vector number is used three times and needs to be unique it would be cleaner. E.g. _Pragma("alias _vector_" ##MY_FUNC_PRIORITY "=my_func") ?
Many thanks

Hi Mike,

Good to hear you got it to work!

Your second question should be solved using this construct:



#define STRING(n) #n
#define STRING_ID(n) STRING(n)

_Pragma("alias _vector_" STRING_ID(0) "=default_handler");
_Pragma("alias _vector_" STRING_ID(1) "=regular_handler");
However, it appears to trip the parser, resulting in this error message:



_Pragma argument should be a single string literal

Somehow the parser doesn't work out that it must concatenated the three strings, like it will for a normal C function call:


printf("alias _vector_" STRING_ID(0) "=default_handler");

It's something I need to pick up with development, as well as your preference to replace the current vector table implementation with the more versatile one that we've been discussing here.

Dealing with the above restriction might be a bit of a challenge. The assembler supports a string operator that, when used in an assembler macro, can turn its argument into a string. So that might do just what you want. However you'd need to think about either using it in a separate assembly module or use __asm to both create and call the macro from C. For the latter I recall having done that a long long time ago. It did eventually work, but it was a bit of a struggle.

Best regards,

Henk-Piet Glas
Technical Product Specialist

Mike_FN
Aug 12th, 2016, 08:16 AM
Hello again, I have already tried the double #define STRINGIFY method and a few variations and gotten this single string error. I may not have time to look further since its not that important, but not to worry.
Another method might be the _Pragma lines might be removed altogether by using the ".text.inttaby.intvec.xxx" sections automatically created by the Tasking compiler in response to "void __interrupt( xxx ) __vector_table( y ) func( void )", instead of defining our own "_vector_xxx" aliases ?

Mike

TASKING.hp.glas
Aug 12th, 2016, 01:08 PM
Hello again, I have already tried the double #define STRINGIFY method and a few variations and gotten this single string error. I may not have time to look further since its not that important, but not to worry.
Another method might be the _Pragma lines might be removed altogether by using the ".text.inttaby.intvec.xxx" sections automatically created by the Tasking compiler in response to "void __interrupt( xxx ) __vector_table( y ) func( void )", instead of defining our own "_vector_xxx" aliases ?

Mike

Hi Mike,

That probably won't work. To see why this is so you must take a peek at the assembly generated from the pragma's:


_vector_0 .equ default_handler
.global _vector_0
_vector_1 .equ regular_handler
.global _vector_1
Note that these are not section names, but just global labels. I've been using the word 'publish' for that earlier. During linking/locating two things will happen with the vector.asm template. First, section `.vtctext.vector` is replaced with the name of `_vector_xxx` and secondly label `_lc_vector_target` is replaced with the associated handler function label. Key here is that the sections are assemled during linking/locating and not during compiling. So the sections `.text.inttaby.intvec.xxx` cannot be used instead, because these already exist at compile time.

Speaking of `.text.inttaby.intvec.xxx`, note that they don't occur in the mapfile any longer, despite the fact that the compiler still produces them. The reason is that they no longer get referenced and the linker kindly deletes them as a result of that. They'll start popping up again as soon as you uncheck the 'delete unreferenced sections' checkbox in the linker optimisation settings. But of course there's no need to do that, as they no longer have purpose.

Best regards,

Henk-Piet Glas
Technical Product Specialist

Mike_FN
Aug 15th, 2016, 05:56 AM
Thanks again, your knowledge is very good and a time saver.

TASKING.hp.glas
Aug 15th, 2016, 09:00 AM
Thanks again, your knowledge is very good and a time saver.

Thanks Mike,

I appreciate that. Happy to help where I can.

Best regards,

Henk-Piet Glas
Technical Product Specialist

TASKING.hp.glas
Aug 16th, 2016, 02:50 AM
Hi Mike,


... Somehow the parser doesn't work out that it must concatenated the three strings, like it will for a normal C function call:


printf("alias _vector_" STRING_ID(0) "=default_handler");

It's something I need to pick up with development, ...

You'll love this I think. Development tells me that _Pragma indeed accepts only one string literal, for it so being defined in C99 6.10.9. In addition they suggest that you can use the following neat alternative that I hadn't thought of myself:


#define _PRAGMA(x) _Pragma(#x)
#define _VECTOR(n,m) _PRAGMA(alias _vector_ ## n = m)
#define PUBLISH(n,m) _VECTOR(n,m)

PUBLISH(0,default_handler)
PUBLISH(1,regular_handler)

Best regards,

Henk-Piet Glas
Technical Product Specialist