Microblaze Trace ...

debugasm wrote on Sunday, October 30, 2016:

Hi,

I have download “Tracealyzer for FreeRTOS” to do some testing on Microblaze CPU. I have used “FreeRTOS Snapshot Recorder v3.0.9.zip”. I followed the guide but I somehow doubt from this point on:

I have create a project with one task that flashes a LED. The program runs smoothly with no integrated trace.

FreeRTOS v9.0.0 with Microblaze CPU + Snapshot Recorder v3.0.9 from Percepio

I have add this code at the end of “FreeRTOSConfig.h”:

/* Include the FreeRTOS+Trace FreeRTOS trace macro definitions. */
#define TRACE_ENTER_CRITICAL_SECTION() portENTER_CRITICAL()
#define TRACE_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL()
#include "trcKernelPort.h"

The compilation is successful, but if I start the program this crash. In debug I noticed that after three, four calls to the Trace functions, the program crash.

I then decided to change code in “FreeRTOSConfig.h” with this:

/* Include the FreeRTOS+Trace FreeRTOS trace macro definitions. */
#define TRACE_ENTER_CRITICAL_SECTION() /* portENTER_CRITICAL() */
#define TRACE_EXIT_CRITICAL_SECTION() /* portEXIT_CRITICAL() */
#include "trcKernelPort.h"

I basically removed the definitions of “ENTER” and “EXIT” from critical section, In this way the program runs quietly and I can generate the trace in memory statically and then be discharged after a few minutes of operation.

The thing is very strange, but how can I check ?

I would be confident about this, because I would buy the tool, but I would try the real utility before proceeding.

Thanks very much.

debugasm

rtel wrote on Sunday, October 30, 2016:

A couple of questions:

Did you call vTraceInitTraceData(); before calling uiTraceStart()?

Did you see
http://percepio.com/2014/10/27/how-to-define-critical-sections-for-the-recorder
?

debugasm wrote on Sunday, October 30, 2016:

Yes, I have call both functions before start scheduler.

I have follow the FreeRTOs example for Win32 :

“FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator”

but with the appropriate changes for Microblaze.

The function:

portENTER_CRITICAL()
portEXIT_CRITICAL()

Already allows nested interrupts, right ?

I also followed the guidance for Zynq:

http://percepio.com/2016/09/13/tracealyzer-for-freertos-on-xilinx-zynq/

debugasm

rtel wrote on Sunday, October 30, 2016:

I don’t think interrupt nesting is supported on the Microblaze (not to
be confused with critical section nesting, which is supported). The
Microblaze macros make use of the Xilinx library function
microblaze_disable_interrupts() to disable interrupts, and that does not
appear to support nesting.

debugasm wrote on Sunday, October 30, 2016:

It’s true but FreeRTOS have this :

/* Critical section macros. */
void vPortEnterCritical( void );
void vPortExitCritical( void );
#define portENTER_CRITICAL(){						  \
    extern volatile UBaseType_t uxCriticalNesting;		\
	microblaze_disable_interrupts();					\
	uxCriticalNesting++;								\
}

#define portEXIT_CRITICAL()	{						  \
    extern volatile UBaseType_t uxCriticalNesting;		\
	/* Interrupts are disabled, so we can */			\
	/* access the variable directly. */					\
	uxCriticalNesting--;								\
	if( uxCriticalNesting == 0 )						\
	{													\
        /* The nesting has unwound and we 				  \
              can enable interrupts again. */				 \   
               portENABLE_INTERRUPTS();						  \
	}													\
}

So it can not be used with FreeRTOS+Trace on Microblaze ?

davedoors wrote on Sunday, October 30, 2016:

Microblaze is the Xilinx softcore, Zynq is an ARM CortexA9. Dont follow the instructions for a totally different part!

debugasm wrote on Monday, October 31, 2016:

Sorry, I know Zynq and Microblaze very well, I have used and use both long enough.

Before you start writing a line of code I have documented “on principle of operation of trace”.

Know that Zynq and Microblaze are different, and that are not compatible. But understand the principle, you can work on any cpu.

I followed the examples and guides:

 To integrate the recorder trace library in an existing FreeRTOS project, the following steps are suggested:

(1) Check that your FreeRTOS version is v7.3 or later.
(2) Locate the Snapshot recorder library package via the Help menu 
        in Tracealyzer and extract its contents.
(3) Add the .c files from GenericRecorderLibSrc in your 
        build project.
(4) Add GenericRecorderLibSrc/Include to your compiler's 
        include path (i.e., in the project settings).
(5) Copy GenericRecorderLibSrc/ConfigurationTemplate/trcConfig.h 
        to GenericRecorderLibSrc/Include.
(6) Open trcConfig.h and...
        
        - Set SELECTED_PORT to match your target processor.
        - Verify that the FREERTOS_VERSION setting matches your 
            version of FreeRTOS.
        - Check the N[Type] settings (e.g., NTask, NQueue, etc.). 
            They define the maximum allowed number of simultaneously
            active objects, i.e., objects that have been created by 
            not deleted.
        - Check the other settings, especially TRACE_RECORDER_STORE_MODE
            and EVENT_BUFFER_SIZE. You don't need to change them, but we
            recommend you have a look. 
            
(7) In your FreeRTOSConfig.h, make sure you have the following
         setting.

        - #define configUSE_TRACE_FACILITY 1

(8) Add the following line in the very end of your FreeRTOSConfig.h

        #ifndef __ASSEMBLER__
            #if configUSE_TRACE_FACILITY == 1
            	#define TRACE_ENTER_CRITICAL_SECTION() portENTER_CRITICAL()
                #define TRACE_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL()
		        #include "trcKernelPort.h"
            #endif
       #endif

(9) In your main() routine, call vTraceInitTraceData() as early as
         possible. It must be placed before any other calls to the
         recorder or FreeRTOS.
    
(10) Call uiTraceStart() at the point you wish to begin recording,
           in the startup or at some later point in the application code.
           Remember to check the return value. A value of 1 indicates
           that the recorder configuration was OK. Otherwise an error
           message is found in RecorderDataPtr->systemInfo. 

Compilation successful, but FreeRTOs crash. After comment “portENTER_CRITICAL()” and “portEXIT_CRITICAL()” all work but I can not say if properly although the trace buffer is filled normally.

Other ideas ?

debugasm

rtel wrote on Monday, October 31, 2016:

I posted this yesterday, but for some reason it has not shown up. It might show up twice now…

I’m reading the page I just linked to and can’t see why you are coming to that conclusion. From the page:

"If you are using a FreeRTOS port that doesn’t implement portSET_INTERRUPT_MASK_FROM_ISR and portCLEAR_INTERRUPT_MASK_FROM_ISR, you need to define TRACE_ENTER_CRITICAL_SECTION and TRACE_EXIT_CRITICAL_SECTION yourself (see trcKernelPortFreeRTOS.h.). However, in such FreeRTOS ports there are no nested interrupts, so critical sections are only needed in task-context. In this case, a generic solution is:

#define TRACE_ENTER_CRITICAL_SECTION() if (IN_TASK_CONTEXT) portENTER_CRITICAL()
#define TRACE_EXIT_CRITICAL_SECTION()  if (IN_TASK_CONTEXT) portEXIT_CRITICAL()

Another solution is to implement a something like the portSET_INTERRUPT_MASK_FROM_ISR solution above. That design is required if your chip allows for nested interrupts."

So it looks like you just need to implement IN_TASK_CONTEXT for the Microblaze, in other words, find a way of knowing if you are inside a critical section or not, and only call portENTER/EXIT_CRITICAL() when you are.

Is there a register you can read in the Microblaze that tells you if you are in an interrupt or not? Normally there would be such a thing.

…just looking now.

The mfmsr() function returns the ‘machine status register’ which has a Exception In Progress bit (EIP, bit 22). If that is 1 then a hardware exception is in process. I’m not sure if it is also set to 1 when a standard interrupt, rather than an error exception, is in process but you can check that. So IN_TASK_CONTEXT would then become:

#define IN_TASK_CONTEXT ( ( mfmsr() & ( 1 << 22 ) ) == 0 )

NOTE: I have not checked if the bit is set inside an interrupt, as well as an exception, so please check that and find an alternative if it isn’t. These are not FreeRTOS questions though, but hardware questions, so I will leave that to you ;o)

debugasm wrote on Tuesday, November 01, 2016:

As always with your help, you reach always the goal.

I thought that FreeRTOS+Trace was already integrated enough, but from what
you’ve made me read, not for all CPUs.

Taking a cue from what you have written, I have documented better.

Basically:

Machine Status Register (MSR)

EIP = bit 22
	
	Exception In Progress
	
	0 = No hardware exception in progress
	1 = Hardware exception in progress
	Only available if configured with exception support

Hardware Exceptions (EIP) trap the following internal error conditions: 

	illegal instruction
	instruction and data bus error
	unaligned access

with hardware divider 

	divide exception

with hardware floating point unit:

	underflow
	overflow
	float division-by-zero
	invalid operation
	denormalized operand error

with a hardware Memory Management Unit:

	Illegal Instruction Exception
	Data Storage Exception
	Instruction Storage Exception
	Data TLB Miss Exception
	Instruction TLB Miss Exception

This bit remain untouched during interrupt therefore it can not be used for the
purpose.

Documenting best I found this:

Machine Status Register (MSR)

IE = bit 30

	Interrupt Enable
	
	0 = Interrupts disabled
	1 = Interrupts enabled
	
The processor disables future interrupts by clearing the IE bit in the MSR. The 
IE bit is automatically set again when executing the RTID instruction.

So during any interrupts in the processor clear MSR “IE” (bit 30) to prevent
others interrupts (prevents nesting).

So I modified the code suggested by you in this way:

/* During any interrupts in the processor clear MSR "IE" (bit 30) */
#define IN_TASK_CONTEXT ( ( mfmsr() & ( 1 << 30 ) ) == 1 )

#define TRACE_ENTER_CRITICAL_SECTION() if (IN_TASK_CONTEXT) portENTER_CRITICAL()
#define TRACE_EXIT_CRITICAL_SECTION()  if (IN_TASK_CONTEXT) portEXIT_CRITICAL()

Compiling again with these changes and restarting the debugging, now everything
works perfectly.

I also modified version of “Trace-Streaming” using a serial port and it works
perfectly well with this.

I do other tests, if not finding other problems, I would say that everything
works fine.

Inspecting the first recorded Trace would say that the tool is amazing, you can
see many things more. Really nice.

Thanks very much.

debugasm

johankraft wrote on Monday, November 07, 2016:

Many thanks for documenting your Microblaze fix. Since FreeRTOS is available for so many architectures, we have not yet been able to provide official ports for all. The current Microblaze port is tagged as “unofficial”, meaning that we have received it from a third party but not yet verified it ourselves. But we will take this opportunity integrate your fix, verify and provide it as an official port.
I hope this can be done by the Tracealyzer v3.1.1 release, probably in december. The upcoming release v3.1.0 is in code freeze now, a shame I didn’t see this earlier…

For questions regarding the FreeRTOS trace recorder, I recommend contacting support (at) percepio.com, where our friendly support engineer Niclas will help you out.

debugasm wrote on Tuesday, November 08, 2016:

The working code is this:

#if (SELECTED_PORT == PORT_XILINX_MICROBLAZE)
	#define TRACE_SR_ALLOC_CRITICAL_SECTION() int __irq_status;

    /* Byte Order */
    #if XPAR_MICROBLAZE_ENDIANNESS
        /* 
         * MicroBlaze Little-Endian Working
         *
         * If interrupt enable, interrupt clearing the IE bit in the MSR 
         */
        #define IN_TASK_CONTEXT ( ( mfmsr() & ( 1 << 1 ) ) != 0 )
    #else
        /* 
         * MicroBlaze Big-Endian Not Tested !!! 
         *        
         * If interrupt enable, interrupt clearing the IE bit in the MSR
         */
        #define IN_TASK_CONTEXT ( ( mfmsr() & ( 1 << 30 ) ) != 0 )
    #endif
    
	#define TRACE_ENTER_CRITICAL_SECTION() __irq_status = IN_TASK_CONTEXT; if (__irq_status) portENTER_CRITICAL()
	#define TRACE_EXIT_CRITICAL_SECTION() if (__irq_status) portEXIT_CRITICAL()
#endif

Add this at the end of “FreeRTOSConfig.h”

/* Prevent the function prototypes being included from asm files. */
#ifndef __ASSEMBLER__
	#if configUSE_TRACE_FACILITY == 1
		#include "trcKernelPort.h"
	#endif
#endif

If user want same address for recordi data use linker script to place recorder data on section of memory:

RecorderDataType RecorderData __attribute__((section(".trace")));

On Linker script:

MEMORY
{
...
TRACE_BASEADDR : ORIGIN = 0x84000000, LENGTH = 0x00400000
...
}

.trace (NOLOAD) : {
   . = ALIGN(8);
   _trace = .;
} > TRACE_BASEADDR

I did not forget anything, I think.

debugasm