[PSoC 5] [LCD 128x64] My Application Program is Running fine with CY8CKIT-050 but in my Hardware it hangs on CY_ISR(IntDefaultHandler) in file name "Cm3Start.c"

dhruvacharya wrote on Saturday, September 26, 2015:

Hi there,

[ FreeRTOS V8.2.1 ] [ PSoC Creator ] [ PSoC 5 ] [ CY8C5868AXI-LP035 ] [ GCC ARM CM3 port ]

I am facing weird problem with my Application on PSoC 5 based hardware. This application is based on FreeRTOS, and application contains 128×64 kind of monochromatic LCD (Graphical LCD), having controller like ks0107.

Please find my Project here (As I am new to this forum I don’t know how to attach my project files so attaching zip file for PSoC Creator 3.2 workspace).

  1. Application program for CY8CKIT-050 here.
  2. Application program for our Hardware here (Only with different PIN usage)

The problem is that if we run this program with the PIN used for CY8CKIT-050 and program it in CY8CKIT-050, it runs smoothly and complete every task as desired with no problem at all. But if we only change the MCU PINs as used in our Hardware and program the Hardware MCU with same program, application runs to certain point and then hang. We tried debug mode and found out that after running for some time application goes to this point :

CY_ISR(IntDefaultHandler)
{

    while(1)
    {
        /***********************************************************************
        * We must not get here. If we do, a serious problem occurs, so go
        * into an infinite loop.
        ***********************************************************************/
    }
}

which is in Cm3Start.c. And at this point application stays in hanged state.

Here please note that this only happens if we used the same program in our Hardware. But if we use it in Kit (CY8CKIT-050), it runs completely fine without any fault.

We would like to also share that we have used FreeRTOS prior to this application, and we have successfully built applications with FreeRTOS.

Will you please check this files and see if we have made any mistake anywhere?

rtel wrote on Saturday, September 26, 2015:

I would guess that the funciton you are ending up in is a default interrupt handler - that is - an interrupt handler that is assigned to every interrupt in the system when the system starts up. Any interrupts used by the application should replace the default with the application specific handler. Therefore it would seem simply that you are using an interrupt for which you have not installed a handler - perhaps because your own hardware is using different pins to the hardware for which the demo was written.

dhruvacharya wrote on Saturday, September 26, 2015:

Hi,

In my above application I only use one Interrupt which is DMA cycle completion interrupt. That is not PIN Specific Interrupt, and for that I have also defined Handler following the method suggested in demo. appart from that no interrupt is used which can be PIN specific. Whatever PIN location changes in the transation are only GPIOs. In PSoC we usally can switch any PIN (mostly Digital GPIO) to any PIN. Any PIN used here is not configured for external hardware interrupt. I also may attach some snapshot of the call stack window in debug mode. If it may help to find out the problem.

rtel wrote on Sunday, September 27, 2015:

Have you installed the interrupt handlers required by FreeRTOS - which
are PendSV, SysTick and SVCCall?

See the “Special note to ARM Cortex-M” section of the section “1” in the
FAQ question “The
application I created compiles, but does not run
”.

Regards.

dhruvacharya wrote on Sunday, September 27, 2015:

FreeRTOS FAQ page you suggested was of the great help for every problem prior to this , but this time it doesnt helped me. I have gone through it once again after your suggestion. I am attaching various function screenshot if you can find any faults.

PS. This conversation is going on in parallel:
http://www.cypress.com/forum/psoc-5-known-problems-and-solutions/freertos-lcd-128x64-my-application-program-running-fine

dhruvacharya wrote on Sunday, September 27, 2015:

Hi I have posted this comment before but I dont know why it couldn’t appeare here:

The [FreeRTOS FAQ page] you suggested was great help for all the problems prior to this one, I have gone through it may times and once again I have gone through that after your suggestion. I am attaching some screenshot here for if you could find if I have made any problem in Interrupt Handlers.

PS : This conversation is going on in parallel:
http://www.cypress.com/forum/psoc-5-known-problems-and-solutions/freertos-lcd-128x64-my-application-program-running-fine

I will update solution to both the thread, if this problem get solved from either. Thanks for the help.

dhruvacharya wrote on Tuesday, September 29, 2015:

Moderator please moderate my comments so others and the experts can see the message.

heinbali01 wrote on Tuesday, September 29, 2015:

Recently I also saw an unknown interrupt un some project, caught by a DefaultHandler.

What I did was to catch every undefined interrupt in a separate handler (it took some copy/pasting). Each handler would just exist of an infinite loop for( ;;)

In my case it turned out that I missed 2 essential defines in my ‘FreeRTOSConfig.h’ :

  #define vPortSVCHandler		SVC_Handler
  #define xPortPendSVHandler	PendSV_Handler

In fact, vPortSVCHandler() and xPortPendSVHandler() were both defined in portable/GCC/ARM_CM4F/port.c, but depending on the platform and compilers, these function names get different actual names.

Like Richard already suggested, I would check especially the implementation of PendSV, SysTick and SVCCall.

And remember: cross-posting is not really appreciated. Please keep anyone updated.

Regards.

rtel wrote on Tuesday, September 29, 2015:

I think on the Cortex-M the number of the currently executing interrupt
can be read directly from one of the NVIC registers, but I can’t
remember which one.

dhruvacharya wrote on Wednesday, September 30, 2015:

@Hein

And remember: cross-posting is not really appreciated. Please keep anyone updated.

Sorry for my mistake. I will avoid it next time. But time is running so fast and nowadays if developer is not able to provide solutions, it hurt really badly in our part of world. But in any case I will keep your point in my mind. Thanks for that.

I actully don’t get your point Hein, sorry for my slow learning capability, when you say:

In my case it turned out that I missed 2 essential defines in my ‘FreeRTOSConfig.h’ :
Like Richard already suggested, I would check especially the implementation of PendSV, SysTick and SVCCall.

Are you trying to say that I need to create this functions by my own instead of using the one presented at *\FreeRTOS\Source\portable\GCC\ARMCM3\port.c * ?

If you are not trying to say that, than are you trying to say that I need to check if this function gets called properly or not? If yes than how may I check that?

I actually first call this vInitCortexHandle above all the task creation and scheduler starting.

void vInitCortexHandle ( void )
{
	/* Initialize the OS vectors - make it ready to create the task, below */
    
    /* Handler for Cortex Supervisor Call (SVC, formerly SWI) - address 11 */
    CyIntSetSysVector( CORTEX_INTERRUPT_BASE + SVCall_IRQn,
        (cyisraddress)vPortSVCHandler );
    
    /* Handler for Cortex PendSV Call - address 14 */
	CyIntSetSysVector( CORTEX_INTERRUPT_BASE + PendSV_IRQn,
        (cyisraddress)xPortPendSVHandler );    
    
    /* Handler for Cortex SYSTICK - address 15 */
	CyIntSetSysVector( CORTEX_INTERRUPT_BASE + SysTick_IRQn,
        (cyisraddress)xPortSysTickHandler );
}

and prior to that I define this

/* Declarations of the exception handlers for FreeRTOS */
extern void xPortPendSVHandler(void);
extern void xPortSysTickHandler(void);
extern void vPortSVCHandler(void);

Will you please help me by clarifying these two queries and provide me some example. Thank you.

@rtel

I think on the Cortex-M the number of the currently executing interrupt
can be read directly from one of the NVIC registers, but I can’t
remember which one.

Are you trying to say that we can find which interrupt cause the execution of default handler? Please elaborate on this; I think we can find the reason for the problem with this direction.
But as we have never came across the problem like this one, we have never bother about NVIC registers and all that, so will you please guide me through this? Meanwhile I am also digging this as much on online references. Thanks for the help.

heinbali01 wrote on Wednesday, September 30, 2015:

Hi Dhruv,

Are you trying to say that I need to create this functions by my
own instead of using the one presented at ARMCM3/port.c ?

No they’re OK and they should be used.

What happened in my M4 port was the following: port.c defines two functions vPortSVCHandler() and xPortPendSVHandler(). These are the ISR’s for resp. SVC_Handler and PendSV_Handler.

The actual names SVC_Handler and PendSV_Handler may vary between platforms and compilers. For that reason, these two defines are used:

    #define vPortSVCHandler       SVC_Handler
    #define xPortPendSVHandler    PendSV_Handler

Are you trying to say that we can find which interrupt cause
the execution of default handler?

Have a look at the IABR register(s) ( google “cortex m3 IABR” ) when it runs into the DefaulHandler again, it indicates which interrupts are active.
I’m very curious which interrupt is triggered and not yet defined.

Regards.

rtel wrote on Wednesday, September 30, 2015:

@rtel

I think on the Cortex-M the number of the currently executing interrupt
can be read directly from one of the NVIC registers, but I can't
remember which one.

Are you trying to say that we can find which interrupt cause the
execution of default handler? Please elaborate on this, I think we can
find the resone problem with this direction.
But as we have never came acrros the problem like this one, we have
never bothor about NVIC registers and all that, so will you please guide
me through this? Meanwhile I am also digging this as much on online
referances. Thanks for the help.

The information you need is in the ARM Cortex-M technical documentation,
I could look it up for you, or you could look it up yourself ;o)

dhruvacharya wrote on Wednesday, September 30, 2015:

Hi Hein,
I just copied and pasted this into FreeRTOSConfig.h

#define vPortSVCHandler       SVC_Handler
#define xPortPendSVHandler    PendSV_Handler

Yet the same problem.

I am studying about IABR and NVIC registers to look forward for the solution. I will update soon.

heinbali01 wrote on Thursday, October 01, 2015:

Hi Dhruv,

Patience can solve any problem :slight_smile:

I made some adaptations to a source file in your repository:

Display.cydsn/Generated_Source/PSoC5/Cm3Start.c
Display.cydsn/codegentemp/Cm3Start.c

( I don’t know which version must be adapted, the sources were equal )

Please find the attachment to this post: Cm3Start.zip

Explanation:

if I’m not mistaken, your PSoC5 has at most 48 interrupt sources.

    #define CY_INT_IRQ_BASE     (16u)
    #define CYINT_IRQ_BASE      (CY_INT_IRQ_BASE)
    #define CY_NUM_INTERRUPTS   (32u)
    #define CY_NUM_VECTORS      (CYINT_IRQ_BASE + CY_NUM_INTERRUPTS)

I declared 48 separate handlers, each one will call vUnknownInterruptHandler() with a numeric parameter:

    static volatile int iInterruptNumber = -1;

    void vUnknownInterruptHandler( int iNumber )
    {
        iInterruptNumber = iNumber;
        while( 1 )
        {
            /* Stop here to inspect 'iInterruptNumber' in a debugger.
            Put a break here. */
            CY_NOP;
        }
    }

    CY_ISR( vHandler_0 ) { vUnknownInterruptHandler(  0 ); }
    CY_ISR( vHandler_1 ) { vUnknownInterruptHandler(  1 ); }
    ...

By default, the above handlers will be used:

    /* This source line will be temporarily replaced: */
    -    CyRamVectors[i] = (i < CY_NUM_ROM_VECTORS) ? RomVectors[i] : &IntDefaultHandler;
    +    CyRamVectors[i] = (i < CY_NUM_ROM_VECTORS) ? RomVectors[i] : pxGetIntvector( i );

Do you understand the idea behind it?
Could you try this out?

Regards.

dhruvacharya wrote on Thursday, October 01, 2015:

@rtel and @Hein,

Thanks for the help. I am determined to solve this problem.

I have gone through Architecture Technical Reference Manual and Register TRM for PSoC 5.

I have found that PSoC 5 generally support 32 external interrupt lines (+ 15 exceptions) and for each Ext Interrupt line it represents a bit position in following register.

  1. NVIC_SETENA0 : Interrupt Enable Set 0-31 : Address = 0xe000e100
  2. NVIC_CLRENA0 : Interrupt Enable Clear 0-31 : Address = 0xe000e180
  3. NVIC_SETPEND0 : Interrupt Pending Set 0-31 : Address = 0xe000e200
  4. NVIC_CLRPEND0 : Interrupt Pending Clear 0-31 : Address = 0xe000e280

Each one is four byte long.

In normal condition: Bit 0 is for my DMA interrupt, which executes accordingly fine and working when problem yet to come. But when the faulty loop stops the execution of the application values which are contained in the respected register is suspicious. I have attached a screenshot for that.

In that you may see that NVIC_SETPEND0 and NVIC_CLRPEND0 contain 0x40000000.

This means that External Interrupt number 30 caused the execution of the default interrupt handler, as I am not using this external Interrupt line in my application and I have not declared handler for that.

Now one important line I have encountered in Architecture TRM that says:

The pending register can also be written by software. When the software writes a 1 to the pending bit, it activates the interrupt.

I don’t know how this bit is set… but please keep reading.

Till now I have not used the suggestion given by @Hein.

As you have suggested the changes, @Hein,

It can’t be made in Cm3Start.c, as every time I build the application It changes to the default version. So In general I have called this changes hard way in the main function before doing anything else:

#ifndef CYINT_IRQ_BASE
#define CYINT_IRQ_BASE      16
#endif /* CYINT_IRQ_BASE */

#define CY_NUM_INTERRUPTS           (32u)
#define CY_NUM_VECTORS              (CYINT_IRQ_BASE + CY_NUM_INTERRUPTS)

extern cyisraddress CyRamVectors[CY_NUM_VECTORS];

int main()
{
	uint32 i;
	
	for (i = 2u; i < CY_NUM_VECTORS; i++)
    {
        CyRamVectors[i] = pxGetIntvector( i ); 
    }

....
....

}

I have avoided using first two location of this vector table because:

  1. Initial Stack Pointer
  2. Reset

Now executing with this extra debug, I have found out that every time vHandler_3 is called, which is location for Hard Fault (Number 3 of the 15 exceptions supported by the PSoC 5 according to Architecture TRM). See attached picture. And what Manual has to say about this exeption:

*The hard fault handler can be caused by:

  1. Usage faults, bus faults, and memory management faults if their handler cannot be executed.
  2. Bus faults during vector fetch (reading of a vector table during exception handling).*

Now The reason for a particular fault is updated in the corresponding status register (for example, BFSR register for bus fault, MFSR for memory management fault, UFSR for Usage Fault, HFSR for Hard Fault).

I am digging more and more to this I will update you soon. Meanwhile if you have other IDEA please share.

Thank you again, To be continued…

dhruvacharya wrote on Thursday, October 01, 2015:

Finally found the cause of the problem.

NVIC_HARD_FAULT_STATUS : Hard Fault Status Register : Address = 0xe000ed2c

This register has value 0x40000000, which means:

Hard Fault activated because a Configurable Fault was received and cannot activate because of priority or because the Configurable Fault is disabled. The Hard Fault handler then has to read the other fault status registers to determine cause.

NVIC_USAGE_FAULT_STATUS : Usage Fault Status Register : Address = 0xe000ed2a

This register has value 0x0001, which means:

UNDEFINSTR : The UNDEFINSTR flag is set when the processor attempts to execute an undefined instruction. This is an instruction that the processor cannot decode. The return PC points to the undefined instruction.

Now what this means? I cannot find the details about why this is happened and how to resolve. Please help me here.

davedoors wrote on Thursday, October 01, 2015:

Does this help? http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html

dhruvacharya wrote on Thursday, October 01, 2015:

Hi Dave,

I just followed the link you provided to further debug. And defined and used the hard fault handler provided in that link.

This hard fault handler called successfully every time fault came up. And it calls the prvGetRegistersFromStack then I go to the location in my disassembly window which that PC register provided (as Guided in above link), it is every time the same location 0x0000270C.

I have attached a screen shot of that location. It is the function called,

0x000026FC str.w	r2, [r3, #1d4]	; 0x1d4
0x00002700 bx	lr
0x00002702 push	{r4, lr}
0x00002704 ldr	r3, [pc, #ac]	; (27b4 <vTaskSwitchContext+0xc4>)
0x00002706 movs	r2, #0
0x00002708 str.w	r2, [r3, #1d4]	; 0x1d4
0x0000270C ldr.w	r2, [r3, #1ac]	; 0x1ac
0x00002710 ldr	r2, [r2, #0]

Here I can find in watch window that R2, R3 and some offset is used, but what I found suspicious is that R2 contains “0xFFFFFFFF” does that means something gone wrong here? I.e **R2 overflowed or something? **

rtel wrote on Thursday, October 01, 2015:

Sorry if this has been asked before, but do you have configASSERT()
defined in your application? Also please tell me which version of
FreeRTOS you are using so I know if the asserts will catch
mis-configured interrupt priorities.

Do you also have configCHECK_FOR_STACK_OVERFLOW
set to 2?

Regards.

dhruvacharya wrote on Friday, October 02, 2015:

Hi @rtel,

Yes I have defined configASSERT().

I have definied this in FreeRTOSConfig.h:

extern void vAssertCalled ( char * u8FileName, int u8LineNum );

#define configASSERT( x )		if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )

And in my c file I have defined vAssertCalled like this :

void vAssertCalled ( char * u8FileName, int u8LineNum )
{
	/* The heap space has been execeeded. */
	taskDISABLE_INTERRUPTS();
	
	( void ) u8LineNum;
	
	uint8 CYXDATA u8TempIndex0=0;
	
	for(u8TempIndex0=0 ; u8TempIndex0<25 ; u8TempIndex0++)
	{
		if(u8FileName[u8TempIndex0]==0)
			break;
		
		u8FaultFileName[u8TempIndex0]= u8FileName[u8TempIndex0];
	}
	
	while( 1 )
    {
        /* Do nothing - this is a placeholder for a breakpoint */
		//LED_4_Write ( LED_4_Read () ^ 0x01 );
		
		//CyDelay(500);
		CY_NOP;
    }
}

I am using FreeRTOS V8.2.1. And In FreeRTOSConfig.h I have this:

#define configCHECK_FOR_STACK_OVERFLOW	2

Thank you.