Interrupt problems, Ver: 9.0.0, Port: PIC32MX

lz1msz wrote on Thursday, June 30, 2016:

We make new project with PIC32MX370F512L. FreeRTOS port is 9.0.0. We have interrupt issues. I attach sample project which demonstrates the problem:
There is interrupt handler for TIMER2, also interrupt setting to the timer. When xSemaphoreCreateMutex() function is called, the interrupt does not work. It doesn’t matter if the scheduler is started or not. I checked already - timer2 is not used by the scheduler for any purpose. The priority level of the timer match the priority level of the handler. The interrupts are enabled.

When i comment the function xSemaphoreCreateMutex(), the interrupts are working. The attached project includes the FreeRTOS config, configuration bits and all needed features for test even on simulator

lz1msz wrote on Thursday, June 30, 2016:

/*******************************************************************************
* Filename:                 TEST_System.c
* Microcontroller:          PIC32MX370F512L
* Hardware:                 -
* Compiler:                 MPLAB XC32 VER 1.40 or higher
* Company:                  SONECO LTD
* Author:                   DIMITAR BELEV - email: xxxx@xxxx
* Creation Date:            2016.06.18
* Description:              This file contains the main() function of the
                            FreeRTOS interrupts test project.
* Modification History:     2016.06.30 - Initial revision
*******************************************************************************/



//******************************** HEADER FILES ********************************
#include <xc.h>                                                                 // Compiler main file
#include <plib.h>                                                               // Peripheral library functions
#include "FreeRTOS.h"                                                           // FreeRTOS main file
#include "semphr.h"                                                             // Needed FreeRTOS defines and typedefs
#include "queue.h"                                                              //
#include "semphr.h"                                                             //
//******************************************************************************



//********************** CONFIGURATION BITS SET IN CODE ************************

// Shadow Register Set Priority Select:
   #pragma config FSRSSEL = PRIORITY_1                                          // SRS Priority 1

// Peripheral Module Disable Configuration:
   #pragma config PMDL1WAY = OFF                                                // Allow multiple reconfigurations

// Peripheral Pin Select Configuration:
   #pragma config IOL1WAY = OFF                                                 // Allow multiple reconfigurations

// PLL Input Divider:
   #pragma config FPLLIDIV = DIV_2                                              // 2x Divider

// PLL Multiplier:
   #pragma config FPLLMUL = MUL_20                                              // 20x Multiplier

// System PLL Output Clock Divider:
   #pragma config FPLLODIV = DIV_1                                              // PLL Divide by 1

// Oscillator Selection Bits:
   #pragma config FNOSC = PRIPLL                                                // Primary Osc w/PLL (XT+,HS+,EC+PLL)

// Secondary Oscillator Enable:
   #pragma config FSOSCEN = OFF                                                 // Disabled

// Internal/External Switch Over:
   #pragma config IESO = OFF                                                    // Disabled

// Primary Oscillator Configuration:
   #pragma config POSCMOD = HS                                                  // HS osc mode

// CLKO Output Signal Active on the OSCO Pin:
   #pragma config OSCIOFNC = OFF                                                // Disabled

// Peripheral Clock Divisor:
   #pragma config FPBDIV = DIV_1                                                // Pb_Clk is Sys_Clk/1

// Clock Switching and Monitor Selection:
   #pragma config FCKSM = CSDCMD                                                // Clock Switch Disable, FSCM Disabled

   #pragma config WDTPS = PS1048576                                             // 1:1048576

// Watchdog Timer Window Enable:
   #pragma config WINDIS = OFF                                                  // Watchdog Timer is in Non-Window Mode

// Watchdog Timer Enable:
   #pragma config FWDTEN = OFF                                                  // WDT Disabled (SWDTEN Bit Controls)

// Watchdog Timer Window Size:
   #pragma config FWDTWINSZ = WINSZ_50                                          // Window Size is 50%

// Background Debugger Enable:
   #pragma config DEBUG = OFF                                                   // Debugger is Disabled

// JTAG Enable:
   #pragma config JTAGEN = OFF                                                  // JTAG Disabled

// ICE/ICD Comm Channel Select:
   #pragma config ICESEL = ICS_PGx1                                             // Communicate on PGEC1/PGED1

// Program Flash Write Protect:
   #pragma config PWP = PWP512K                                                 // First 512K

// Boot Flash Write Protect bit:
   #pragma config BWP = ON                                                      // Protection Enabled

// Code Protect:
   #pragma config CP = ON                                                       // Protection Enabled
//******************************************************************************



//**************************** FUNCTION PROTOTYPES *****************************
//void __ISR(_TIMER_2_VECTOR, IPL4AUTO) TMR2InterruptHandler(void);
//******************************************************************************



//****************************** GLOBAL VARIABLES ******************************
SemaphoreHandle_t xSemaphoreTestHandle;                                         // Semaphore handle for the interrupts test
//******************************************************************************



//***************************** EXTERNAL VARIABLES *****************************
//******************************************************************************



/*******************************************************************************
* Function Name:                void main(void)
* Input Parameters:             NONE
* Returned Value:               NONE
* Precondition:                 NONE
* Affected Global Objects:      ALL
* Side Effects                  NONE
* Company:                      SONECO LTD
* Author:                       DIMITAR BELEV - email: xxxx@xxxx
* Creation Date:                2016.06.18
* Short Description:            main function of the TDS3002 project.
* Remark:                       NONE
* Example:                      NONE                                            // This function does not have caller
*******************************************************************************/
void main(void)
{
    // Enable the pre-fetch cache module to achieve 100MHz Tcy:
    CHECON = 0b00000000000000000000001100110010;
    INTCONbits.MVEC = 1;
    
    // Initialize the used tick timer for the TDS3XXX protocol timeouts:
    PR2 = 10937;
    T2CON = 0b00000000000000001000000001100000;                                 // TMR2_ON, Continue operation in IDLE, Gate accumulation disabled, Prescale 1:64, 16bit mode, Fp clock
    
    // Initialize the TIMER2 interrupts:
    IFS0bits.T2IF = 0;                                                          // Clear the TIMER2 Interrupt Flag
    IPC2bits.T2IP = 1;                                                          // Set the TIMER2 interrupt priority
    IPC2bits.T2IS = 0;                                                          // Set the TIMER2 interrupt priority
    IEC0bits.T2IE = 1;                                                          // Enable the TIMER2 interrupts
    
    // Firmware modules initialization:
    xSemaphoreTestHandle = xSemaphoreCreateMutex();                             // The RTOS tasks control objects - semaphores, queues...
    
    //vTaskStartScheduler();
    INTEnableSystemMultiVectoredInt();
    while(1)
    {
    }
    return;
} // End of main()

/*******************************************************************************
* Function Name:                void __ISR(_TIMER_2_VECTOR, IPL4AUTO) TMR2InterruptHandler(void)
* Input Parameters:             NONE
* Returned Value:               NONE
* Precondition:                 The global interrupts must be disabled
* Affected Global Objects:      ALL
* Side Effects                  NONE
* Company:                      SONECO LTD
* Author:                       DIMITAR BELEV - email: xxxx@xxxx
* Creation Date:                2016.06.30
* Short Description:            Interrupt service routine for TIMER2 interrupt
                                handling
* Remark:                       NONE
* Example:                      NONE                                            // This function does not have caller
*******************************************************************************/
void __ISR(_TIMER_2_VECTOR, IPL1SRS) TMR2InterruptHandler(void)
{
    // Clear the TIMER2 Interrupt flag:
    IFS0bits.T2IF = 0;
} // End of TMR2InterruptHandler()

void vAssertCalled( const char * pcFile, unsigned long ulLine )
{
volatile unsigned long ul = 0;

	( void ) pcFile;
	( void ) ulLine;

	__asm volatile( "di" );
	{
		/* Set ul to a non-zero value using the debugger to step out of this
		function. */
		while( ul == 0 )
		{
			portNOP();
		}
	}
	__asm volatile( "ei" );
}

void vApplicationTickHook(void)
{
} // End of vApplicationTickHook()

void vApplicationIdleHook(void)
{
} // End of vApplicationTickHook()

// End of TEST_System.c

lz1msz wrote on Thursday, June 30, 2016:

In the attached project file is also the FreeRTOS configuration, the main related settings are:

#define configUSE_PREEMPTION					1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION	1
#define configUSE_IDLE_HOOK						1
#define configUSE_TICK_HOOK						1
#define configTICK_RATE_HZ						( ( TickType_t ) 1000 )
#define configCPU_CLOCK_HZ						( 100000000UL )
#define configPERIPHERAL_CLOCK_HZ				( 100000000UL )
#define configMAX_PRIORITIES					( 5UL )
#define configMINIMAL_STACK_SIZE				( 300 )
#define configISR_STACK_SIZE					( 250 )
#define configTOTAL_HEAP_SIZE					( ( size_t ) 9120 )
#define configMAX_TASK_NAME_LEN					( 15 )
#define configUSE_TRACE_FACILITY				0
#define configUSE_16_BIT_TICKS					1
#define configIDLE_SHOULD_YIELD					1
#define configUSE_MUTEXES						1
#define configCHECK_FOR_STACK_OVERFLOW			0
#define configQUEUE_REGISTRY_SIZE				0
#define configUSE_RECURSIVE_MUTEXES				1
#define configUSE_MALLOC_FAILED_HOOK			0
#define configUSE_APPLICATION_TASK_TAG			0
#define configUSE_COUNTING_SEMAPHORES			1
#define configGENERATE_RUN_TIME_STATS			0
#define configSUPPORT_DYNAMIC_ALLOCATION        1

rtel wrote on Thursday, June 30, 2016:

In your main() function - the call to xSemaphoreCreateMutex() - or ANY FreeRTOS API function - will deliberately leave interrupts disabled. When the scheduler starts, interrupts will automatically be enabled again.

This is done to prevent interrupts attempting to use an RTOS service or perform a context switch before the scheduler has been started.

davedoors wrote on Thursday, June 30, 2016:

point 3 http://www.freertos.org/FAQHelp.html

lz1msz wrote on Thursday, June 30, 2016:

Hi, Thanks for the information, there are two points:

If you check the main(function) - in the test case when the scheduler is not used - There is INTEnableSystemMultiVectoredInt() call /After the API usage/, which enables the interrupts manually even if they are disabled by the xSemaphoreCreateMutex() API call.

Second point is, that if i allow the scheduler to start (even with no created tasks the Idle task will be executed all time), the interrupts does not start and the idle task just runs all time without interruption

My be you mean, that the xSemaphoreCreateMutex() disables the interrupts in such a way, that only vTaskStartScheduler() can enable them and the standard peripheral library for the interrupts will not work until the scheduler is started? In this case i need to double check what happens in this case and will return feedback?

Thank you for your time, if you need anything from our side, just let me know.
Kind regards
Dimitar

rtel wrote on Thursday, June 30, 2016:

If you check the main(function) - in the test case when the scheduler is
not used - There is INTEnableSystemMultiVectoredInt() call /After the
API usage/, which enables the interrupts manually even if they are
disabled by the xSemaphoreCreateMutex() API call.

Hmm. The FreeRTOS code masks priority bits in the _CP0_STATUS register.
I think INTEnableSystemMultiVectoredInt() operates on a different
register, maybe using a global enable/disable bit, so calling
INTEnableSystemMultiVectoredInt() will not unmask the interrupts that
were masked by FreeRTOS. Try calling portENABLE_INTERRUPTS() instead.

lz1msz wrote on Friday, July 01, 2016:

Hi, I made the test, the interrupts are now working, thanks for the suggestion. The next problem is, that when i start the scheduler, the MCU resets after 1-2sec after the scheduler is started. If i dnot’t start the scheduler, the MCU stays stable. The problem is even when no task is created, no api functions are called prior the vTaskStartScheduler(). As far as my debug tool says is: “Target halted due to Software Breakpoint in user code”. I provide test code: Empty main function, no interrupts enabled, no tasks creatated. In debug mode i place breakpoint inside the idle task tick hook and it breaks many time, but when i run the target, it resets.
Due to this project is migration from PIC24E part, if we manage to stabilize the interrupts and general behavior here, we can port our application level without issues, thanks in advance: The FreeRTOS config and configuration bits remai unchanged.

void main(void)
{
// Enable the pre-fetch cache module to achieve 100MHz Tcy:
CHECON = 0b00000000000000000000001100110010;

vTaskStartScheduler();
while(1)
{
}
return;

} // End of main()

lz1msz wrote on Friday, July 01, 2016:

Hi, I made the test, the interrupts are now working, thanks for the suggestion. The next problem is, that when i start the scheduler, the MCU resets after 1-2sec after the scheduler is started. If i dnot’t start the scheduler, the MCU stays stable. The problem is even when no task is created, no api functions are called prior the vTaskStartScheduler(). As far as my debug tool says is: “Target halted due to Software Breakpoint in user code”. I provide test code: Empty main function, no interrupts enabled, no tasks creatated. In debug mode i place breakpoint inside the idle task tick hook and it breaks many time, but when i run the target, it resets.
Due to this project is migration from PIC24E part, if we manage to stabilize the interrupts and general behavior here, we can port our application level without issues, thanks in advance: The FreeRTOS config and configuration bits remai unchanged.

void main(void)
{
// Enable the pre-fetch cache module to achieve 100MHz Tcy:
CHECON = 0b00000000000000000000001100110010;

vTaskStartScheduler();
while(1)
{
}
return;

} // End of main()

davedoors wrote on Friday, July 01, 2016:

There is a PIC32MX demo in the FreeRTOS download that runs stable for many years. Copy the pragmas and init code from that.