Using the ASCLIN module from Aurix (interrupt issue)

Forum related to ERIKA Enterprise and RT-Druid version 2

Moderator: paolo.gai

Locked
leoecco

Using the ASCLIN module from Aurix (interrupt issue)

Post by leoecco »

Hi,

I'm trying to employ the ASCLIN module from aurix (serial comm.) in order to communicate with a PC host.
Infineon provides a library (libiLLD) which contains the functions required to properly configure the ACLIN module and to send/receive data.

Anyway, after I call the function to transmit data, an interrupt signal is generated* by the ASCLIN module and then the aurix comes to a "halt"... in the call stack (depicted by a debug tool) the last call is to a EE_tc_disableIRQ() function.

I suspect this is caused because ErikaOS is not aware that the ASCLIN interrupt can be triggered.
My question, hence, would be "how can I inform ErikaOS that such interrupt can be triggered"?

Using the ISR keyword inside the .oil file does not seem to do the trick...

Any help would be greatly appreciated!

* The documentation from aurix is a bit difficult to grasp. It mentions that a "transmit interrupt" signals the "TxFIFO level event ( FLAGS .TFL)".
e.guidieri

Re: Using the ASCLIN module from Aurix (interrupt issue)

Post by e.guidieri »

Hi,

if the programs halt means that the Interrupt vector is ill configured and the default handler for an unconfigured interrupt is taken.

To correctly configure the interrupt you have to assicure that the PRIORITY used in the OIL file correspond to priority configured on the SRC register of the source you want to handle...

Could you copy here your .oil configuration and the call to the APIs to configure the driver (I suppose that the priority for the source is given in that way).

Errico
leoecco

Re: Using the ASCLIN module from Aurix (interrupt issue)

Post by leoecco »

Hi Errico, thanks for the quick answer.

So let me structure the info I have about the problem in parts.

Firstly, it seems like I overlooked something and I am not actually able to use the keyword ISR inside the .oil file (I was editing it out of eclipse, and some of my changes have not been taken into account).

Here is how the beginning of the .oil file looks like:

Code: Select all

CPU test_application {
  OS EE {
    EE_OPT = "EE_DEBUG";
    EE_OPT = "EE_VERBOSE";
    EE_OPT = "EE_EXECUTE_FROM_RAM";
    EE_OPT = "EE_SAVE_TEMP_FILES";
    //EE_OPT = "EE_MM_OPT";
    EE_OPT = "EE_ICACHE_ENABLED";
    EE_OPT = "EE_DCACHE_ENABLED";
    EE_OPT = "ATDEMO";
	EE_OPT = "__TC27XX__";

    REMOTENOTIFICATION = USE_RPC;
    CFLAGS ="-fdata-sections -ffunction-sections";
    CFLAGS ="-Os";
    CFLAGS ="-I/home/ecco/iTUBS/workspace/at-demo2/Include";
    CFLAGS ="-I/home/ecco/iTUBS/workspace/at-demo2/Include/SrvSw";
    CFLAGS ="-I/home/ecco/iTUBS/workspace/at-demo2/Include/_Reg";

    LDFLAGS ="-Wl,--gc-sections";
    LDFLAGS ="-L/home/ecco/iTUBS/workspace/at-demo2/Libs";      
    LIBS ="-liLLD";

    MASTER_CPU = "master";

    CPU_DATA = TRICORE {
      ID = "master";
      CPU_CLOCK = 200.0;
      // APP_SRC = "master.c ledctl.c lcd.c ./GenericTaskset/src/gt_core.c ./GenericTaskset/os/gt_os_erika.c ./GenericTaskset/cfg/gt_tasks.c ./GenericTaskset/cfg/gt_hooks.c";
      APP_SRC = "master.c lcd.c ledctl.c ./GenericTaskset/src/gt_core.c ./GenericTaskset/os/gt_os_erika.c ./GenericTaskset/cfg/gt_tasks.c ./GenericTaskset/cfg/gt_hooks.c";
      MULTI_STACK = TRUE;
      SYS_STACK_SIZE = 2048;
      COMPILER_TYPE = GNU;
    };

    CPU_DATA = TRICORE {
      ID = "slave1";
      APP_SRC = "slave1.c ledctl.c";
      MULTI_STACK = TRUE;
      SYS_STACK_SIZE = 256;
      COMPILER_TYPE = GNU;
    };

    CPU_DATA = TRICORE {
      ID = "slave2";
      APP_SRC = "slave2.c ledctl.c";
      MULTI_STACK = TRUE;
      SYS_STACK_SIZE = 256;
      COMPILER_TYPE = GNU;
    };

    MCU_DATA = TRICORE {
      MODEL = TC27x;
    };

    BOARD_DATA = TRIBOARD_TC2X5;

    STATUS = EXTENDED;
    ERRORHOOK = TRUE;
    USERESSCHEDULER = FALSE;
    ORTI_SECTIONS = ALL;

    KERNEL_TYPE = ECC1;
  };

    ISR asclin0TxISR {
      CATEGORY = 2;
      PRIORITY = 1;
    };

    ISR asclin0RxISR {
      CATEGORY = 2;
      PRIORITY = 2;
    };

    ISR asclin0ErISR {
      CATEGORY = 2;
      PRIORITY = 3;
    };
     
    // (...) Remaining of the .oil is omitted.
};

When I try to generate the system, RT-druid tells me that:

Code: Select all

Rebuild the project at-demo2. Config file:
	/at-demo2/conf.oil
ERROR > Task asclin0TxISR is mapped to a not valid cpu (default_cpu \/ EE)
ERROR > Task asclin0RxISR is mapped to a not valid cpu (default_cpu \/ EE)
ERROR > Task asclin0ErISR is mapped to a not valid cpu (default_cpu \/ EE)
Check and fill folder at-demo2/Debug
	at-demo2/Debug/make_launcher.bat	OK

Secondly, find below how the ASCLIN module is configured. The setup_serial_comm() functions contains the initialization steps (but before the function we have some structure and handler declarations. The IFX_INTERRUPT is a macro and its definition is provided in the second code box.

Code: Select all

static IfxAsclin_Asc asc;
#define ASC_TX_BUFFER_SIZE 64
static uint8 ascTxBuffer[ASC_TX_BUFFER_SIZE + sizeof(Ifx_Fifo) + 8];
#define ASC_RX_BUFFER_SIZE 64
static uint8 ascRxBuffer[ASC_RX_BUFFER_SIZE + sizeof(Ifx_Fifo) + 8];

// Interrupt definition
#define IFX_INTPRIO_ASCLIN0_TX 1
#define IFX_INTPRIO_ASCLIN0_RX 2
#define IFX_INTPRIO_ASCLIN0_ER 3


IFX_INTERRUPT(asclin0TxISR, 0, IFX_INTPRIO_ASCLIN0_TX)
{
IfxAsclin_Asc_isrTransmit(&asc);
}
IFX_INTERRUPT(asclin0RxISR, 0, IFX_INTPRIO_ASCLIN0_RX)
{
IfxAsclin_Asc_isrReceive(&asc);
}
IFX_INTERRUPT(asclin0ErISR, 0, IFX_INTPRIO_ASCLIN0_ER)
{
IfxAsclin_Asc_isrError(&asc);
}

// Struct containing configuration of the serial communication module.
IfxAsclin_Asc_Config ascConfig;

void setup_serial_comm()
{
	// Configuration structure is initialized
	IfxAsclin_Asc_initModuleConfig(&ascConfig, &MODULE_ASCLIN3);

	// And now we perform our configuration...
	/* set the desired baudrate */
	ascConfig.baudrate.prescaler = 1;

	/* FDR values will be calculated in initModule */
	ascConfig.baudrate.baudrate = 9600;

	/* ISR priorities and interrupt target */
	ascConfig.interrupt.txPriority = IFX_INTPRIO_ASCLIN0_TX;
	ascConfig.interrupt.rxPriority = IFX_INTPRIO_ASCLIN0_RX;
	ascConfig.interrupt.erPriority = IFX_INTPRIO_ASCLIN0_ER;
	ascConfig.interrupt.typeOfService = (IfxSrc_Tos)IfxCpu_getCoreId();

	/* FIFO configuration */
	ascConfig.txBuffer = &ascTxBuffer;
	ascConfig.txBufferSize = ASC_TX_BUFFER_SIZE;
	ascConfig.rxBuffer = &ascRxBuffer;
	ascConfig.rxBufferSize = ASC_RX_BUFFER_SIZE;

	/* pin configuration */
	const IfxAsclin_Asc_Pins pins = {
	NULL, IfxPort_InputMode_pullUp, /* CTS pin not used */
	&IfxAsclin3_RXD_P32_2_IN, IfxPort_InputMode_pullUp, /* Rx pin */
	NULL, IfxPort_OutputMode_pushPull, /* RTS pin not used */
	&IfxAsclin3_TX_P15_7_OUT, IfxPort_OutputMode_pushPull, /* Tx pin */
	IfxPort_PadDriver_cmosAutomotiveSpeed1
	};
	ascConfig.pins = &pins;

	/* Manually set pad driver to speed grade 1 */
	/*(otherwise 3v3 is not seen as a '1' )     */
       IfxPort_setPinPadDriver(&MODULE_P15,7,
	                            IfxPort_PadDriver_cmosAutomotiveSpeed1) ;

	/* Module is finally initialized */
	IfxAsclin_Asc_initModule(&asc, &ascConfig);

	IfxPort_setPinPadDriver(&MODULE_P32,2,
	                        IfxPort_PadDriver_cmosAutomotiveSpeed1) ;

    IfxCpu_Irq_installInterruptHandler(&asclin0TxISR, IFX_INTPRIO_ASCLIN0_TX);
    IfxCpu_Irq_installInterruptHandler(&asclin0RxISR, IFX_INTPRIO_ASCLIN0_RX); 
    IfxCpu_Irq_installInterruptHandler(&asclin0ErISR, IFX_INTPRIO_ASCLIN0_ER);
    IfxCpu_enableInterrupts();
}

Code: Select all

#ifndef IFX_INTERRUPT
#define IFX_INTERRUPT(isr, vectabNum, prio) IFX_INTERRUPT_INTERNAL(isr, vectabNum, prio)
#endif
#ifndef IFX_INTERRUPT_INTERNAL
#define IFX_INTERRUPT_INTERNAL(isr, vectabNum, prio) \
__asm__ (".ifndef .intr.entry.include                        \n"\
		".altmacro                                           \n"\
		".macro .int_entry.2 intEntryLabel, name # define the section and inttab entry code \n"\
        "	.pushsection .\\intEntryLabel,\"ax\",@progbits   \n"\
        "	__\\intEntryLabel :                              \n"\
        "		svlcx                                        \n"\
        "		movh.a  %a14, hi:\\name                      \n"\
        "		lea     %a14, [%a14]lo:\\name                \n"\
        "		ji      %a14                                 \n"\
        "	.popsection                                      \n"\
		".endm                                               \n"\
		".macro .int_entry.1 prio,vectabNum,u,name           \n"\
			".int_entry.2 intvec_tc\\vectabNum\\u\\prio,(name) # build the unique name \n"\
		".endm                                               \n"\
        "                                                    \n"\
		".macro .intr.entry name,vectabNum,prio              \n"\
			".int_entry.1 %(prio),%(vectabNum),_,name # evaluate the priority and the cpu number \n"\
		".endm                                               \n"\
		".intr.entry.include:                                \n"\
		".endif                                              \n"\
        ".intr.entry "#isr","#vectabNum","#prio               );\
IFX_EXTERN void __attribute__ ((interrupt_handler)) isr(); \
void isr (void)
#endif /* IFX_INTERRUPT_INTERNAL */

#endif /*defined(IFX_USE_SW_MANAGED_INT)*/
So yes, the main problem is that I'm unable to use the ISR definition inside the CPU definition in the .oil file.

Again, any help is greatly appreciated.
e.guidieri

Re: Using the ASCLIN module from Aurix (interrupt issue)

Post by e.guidieri »

Since you are in multicore environment (more than done CPU_DATA configured) you have top map objects (TASKs, ISRs ecc...) on cores, adding CPU_ID field, e.g. CPU_ID="master";
leoecco

Re: Using the ASCLIN module from Aurix (interrupt issue)

Post by leoecco »

Hi Errico, thank you again for the quick answer.

Here are the new developments. I updated the .oil file... it now looks like the following:

Code: Select all

CPU test_application {
  OS EE {
    EE_OPT = "EE_DEBUG";
    EE_OPT = "EE_VERBOSE";
    EE_OPT = "EE_EXECUTE_FROM_RAM";
    EE_OPT = "EE_SAVE_TEMP_FILES";
    //EE_OPT = "EE_MM_OPT";
    EE_OPT = "EE_ICACHE_ENABLED";
    EE_OPT = "EE_DCACHE_ENABLED";
    EE_OPT = "ATDEMO";
	EE_OPT = "__TC27XX__";

    REMOTENOTIFICATION = USE_RPC;

    /* Needed Otherwise Slave1 Application Cannot be located in PSPR
       (not enough space) */


    CFLAGS ="-fdata-sections -ffunction-sections";
    CFLAGS ="-Os";
    CFLAGS ="-I/home/ecco/iTUBS/workspace/at-demo2/Include";
    CFLAGS ="-I/home/ecco/iTUBS/workspace/at-demo2/Include/SrvSw";
    CFLAGS ="-I/home/ecco/iTUBS/workspace/at-demo2/Include/_Reg";

    LDFLAGS ="-Wl,--gc-sections";
    LDFLAGS ="-L/home/ecco/iTUBS/workspace/at-demo2/Libs";      
    LIBS ="-liLLD";


    


    MASTER_CPU = "master";

    CPU_DATA = TRICORE {
      ID = "master";
      CPU_CLOCK = 200.0;
      // APP_SRC = "master.c ledctl.c lcd.c ./GenericTaskset/src/gt_core.c ./GenericTaskset/os/gt_os_erika.c ./GenericTaskset/cfg/gt_tasks.c ./GenericTaskset/cfg/gt_hooks.c";
      APP_SRC = "master.c lcd.c ledctl.c ./GenericTaskset/src/gt_core.c ./GenericTaskset/os/gt_os_erika.c ./GenericTaskset/cfg/gt_tasks.c ./GenericTaskset/cfg/gt_hooks.c";
      MULTI_STACK = TRUE;
      SYS_STACK_SIZE = 2048;
      COMPILER_TYPE = GNU;
    };

    CPU_DATA = TRICORE {
      ID = "slave1";
      APP_SRC = "slave1.c ledctl.c";
      MULTI_STACK = TRUE;
      SYS_STACK_SIZE = 256;
      COMPILER_TYPE = GNU;
    };

    CPU_DATA = TRICORE {
      ID = "slave2";
      APP_SRC = "slave2.c ledctl.c";
      MULTI_STACK = TRUE;
      SYS_STACK_SIZE = 256;
      COMPILER_TYPE = GNU;
    };

    MCU_DATA = TRICORE {
      MODEL = TC27x;
    };

    BOARD_DATA = TRIBOARD_TC2X5;

    STATUS = EXTENDED;
    ERRORHOOK = TRUE;
    USERESSCHEDULER = FALSE;
    ORTI_SECTIONS = ALL;

    KERNEL_TYPE = ECC1;
  };


    ISR asclin0TxISR {
      CPU_ID   = "master";
      CATEGORY = 2;
      PRIORITY = 2;
      HANDLER  = "asclin0TxISR";
    };

    ISR asclin0RxISR {
      CPU_ID   = "master";
      CATEGORY = 2;
      PRIORITY = 3;
      HANDLER  = "asclin0RxISR";
    };

    ISR asclin0ErISR {
      CPU_ID   = "master";
      CATEGORY = 2;
      PRIORITY = 4;
      HANDLER  = "asclin0ErISR";
    };
   // (...) remaining of the file
};
Now I am able to generate the system, although I do get the following warnings:

Code: Select all

C    master.c
In file included from /home/ecco/.eclipse/org.eclipse.platform_3.8_155965261/plugins/com.eu.evidence.ee_2.7.0.N20160609_1458/ee_files/pkg/ee.h:50:0,
                 from ../../shared.h:4,
                 from ../../master.c:41:
./eecfg.h:203:0: warning: "EE_TC_2_ISR" redefined [enabled by default]
./eecfg.h:180:0: note: this is the location of the previous definition
In file included from /home/ecco/.eclipse/org.eclipse.platform_3.8_155965261/plugins/com.eu.evidence.ee_2.7.0.N20160609_1458/ee_files/pkg/ee.h:50:0,
                 from ../../shared.h:4,
                 from ../../master.c:41:
./eecfg.h:203:0: warning: "EE_TC_2_ISR" redefined [enabled by default]
./eecfg.h:180:0: note: this is the location of the previous definition
Anyway, the Aurix now does not halt!!! (which means that it was definitely an interrupt issue).
However, the interrupt handler is not being called... This is how I'm defining it now:

Code: Select all

ISR(asclin0TxISR)
{
LEDCTL_On(2);
IfxAsclin_Asc_isrTransmit(&asc);
}

ISR(asclin0RxISR)
{
IfxAsclin_Asc_isrReceive(&asc);
}

ISR(asclin0ErISR)
{
IfxAsclin_Asc_isrError(&asc);
}
Notice how in the handling routine for the transmit event I am turning on a LED.
Well, during run time, the led is never turned on, which probably means that the interrupt routine is not being called.


I also tried to define the interrupt handling routines using the macros from infineon:

Code: Select all

IFX_INTERRUPT(asclin0TxISR, 0, IFX_INTPRIO_ASCLIN0_TX)
{
IfxAsclin_Asc_isrTransmit(&asc);
}
IFX_INTERRUPT(asclin0RxISR, 0, IFX_INTPRIO_ASCLIN0_RX)
{
IfxAsclin_Asc_isrReceive(&asc);
}
IFX_INTERRUPT(asclin0ErISR, 0, IFX_INTPRIO_ASCLIN0_ER)
{
IfxAsclin_Asc_isrError(&asc);
}
The priority assignments are the same as employed in the conf.oil file:

Code: Select all

// Interrupt definition
#define IFX_INTPRIO_ASCLIN0_TX 2 // I had to start from 2 because 1 is reserved by erikaos.
#define IFX_INTPRIO_ASCLIN0_RX 3
#define IFX_INTPRIO_ASCLIN0_ER 4

So, in summary, the system is not halting anymore when an interrupt is triggered. But it seems like the proper interrupt handling routine is not been called... Any ideas?
e.guidieri

Re: Using the ASCLIN module from Aurix (interrupt issue)

Post by e.guidieri »

Start from priorità 3.

You didn't post it but probably you have The system timer configured and this means that The OS need 2 priority: one for system timer and one for multicore communication.
leoecco

Re: Using the ASCLIN module from Aurix (interrupt issue)

Post by leoecco »

Yup, that did the trick. It is now printing :)

Thanks a lot for your help!
MatzeB.

Re: Using the ASCLIN module from Aurix (interrupt issue)

Post by MatzeB. »

By the way, we (Leo and me) figured also out, that the LIBS parameter is missing for the default AURIX/Tricore LD call. Therefore we added an $(LIBS) in ./ee_files/pkg/cfg/arch/rules_infineon_tc_generic.mk at the end of line 263

Code: Select all

### Target file creation ###
$(TARGET_NAME).elf: $(OBJS) $(LIBDEP) $(LINKDEP)
        @echo "LD $@";
        $(QUIET)$(EE_LINK) $(OPT_LINK) $(TARGET_LD_FILE) $(OBJS) $(LIBDEP) $(LINK_REDIRECT) $(LIBS)
        @echo "************************************"
        @echo "Compilation terminated successfully!"
Otherwise, assigning a lib to LIBS = inside of the conf.oil file, does not have any effect and therefore the linker starts crying because of undefined function references ;)

Best regards
Matthias
Locked