• AVR Freaks

AnsweredHot!32-bit timer period register dependent interrupt functionality

Author
SEY
New Member
  • Total Posts : 2
  • Reward points : 0
  • Joined: 2019/09/22 12:42:27
  • Location: 0
  • Status: offline
2019/10/08 11:47:44 (permalink)
0

32-bit timer period register dependent interrupt functionality

Hello all,
 
I have a fresh installation of MPLAB X and the XC32 compiler:
 
MPLAB X version:    
V5.25
 
Operating System and version:    
MAC OS High Sierra 10.13.6
 
Compiler version:
XC32 (v2.30)    
 
Device name:    
PIC32 MZ EF Curiosity Development Board with
PIC32MZ2048EFM100
 
Debugger:
Snap ICD
 
I modified the example project from https://microchipdevelope...amples-interrupt-usage to run on my curiosity board to toggle LED1 and LED2. This runs fine. Then I extended Timer 4 to a 32-bit timer. This runs also fine. But after calculation of the new value for PR4 and run the program I figured out that my calculated values for PR2(15625) and PR4(78125) were not correct, since the measured periods were slightly to long, approximately 6 us. I realized my mistake at the period calculation and decremented both period registers by one. Let the program run, but now, LED2 does not toggle any more. LED1 with Timer 2 works well, but interrupt for Timer 4 will not trigger anymore. If I let Timer 2 off after initialization, Timer 4 interrupt works well. When I change start value TMR4 from zero to 1, both timer interrupts work well. In all tested cases were PR4 = (PR2 x n) + (n-1) -> PR2=15624 and n=1,2,3,4,5,6  and start values for TMR2=0 and TMR4=0 observed the behavior that Timer 5 interrupt does not work correctly.
 
I think the problem I am facing, is independent of the MPLAB and compiler version or debugger.
 
Has anyone an idea what goes wrong here.
 
Thanks. Burkhard
 
/*
** main.c
**
** Project: interrupt-usage-multi
**
** Date: 07-Oct-2019
** Revision:
** Author: 
**
** Comments: Timer 2-driven(Timer Type B 16-bit) ISR used to toggle LED LED1 every 100ms
** Timer 4/5-driven (Timer Type B 32-bit) ISR used to toggle LED LED2 every 500ms
**
** Hardware Design Reference:
** Curiosity PIC32MZEF Dev Board
**
** Dependencies:
**
**
** User Guide:
**
**
*/
/************************************************************************
SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP TECHNOLOGY INC OR ITS LICENSORS BE LIABLE OR OBLIGATED
UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY,
OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
**************************************************************************/
/** INCLUDES ******************************************************************/
#include <xc.h> /* contains Vector Name/Number Macros */
#include <sys/attribs.h> /* contains __ISR() Macros */
#include "proc/p32mz2048efm100.h"
/** CONFIGURATION *************************************************************/
// Key Settings:
// OSCILLATOR: 24MHz EC Oscillator w. PLL
// SYSCLK = 200 MHz (set in config bits), PBxCLK = 10 MHz (set in application code)
// JTAG PORT: Disabled
// WATCHDOG TIMER: Disabled
// DEBUG/PGM PINS: PGEC2/PGED2
// DEVCFG3
//#pragma config USERID = 0xFFFF // Enter Hexadecimal value (Enter Hexadecimal value)
#pragma config FMIIEN = OFF // Ethernet RMII/MII Enable (MII Enabled)
#pragma config FETHIO = ON // Ethernet I/O Pin Select (Default Ethernet I/O)
#pragma config PGL1WAY = ON // Permission Group Lock One Way Configuration (Allow only one reconfiguration)
#pragma config PMDL1WAY = ON // Peripheral Module Disable Configuration (Allow only one reconfiguration)
#pragma config IOL1WAY = ON // Peripheral Pin Select Configuration (Allow only one reconfiguration)
#pragma config FUSBIDIO = ON // USB USBID Selection (Controlled by the USB Module)
// DEVCFG2
#pragma config FPLLIDIV = DIV_3 // System PLL Input Divider (3x Divider)
#pragma config FPLLRNG = RANGE_5_10_MHZ // System PLL Input Range (5-10 MHz Input)
#pragma config FPLLICLK = PLL_POSC // System PLL Input Clock Selection (POSC is input to the System PLL)
#pragma config FPLLMULT = MUL_50 // System PLL Multiplier (PLL Multiply by 50)
#pragma config FPLLODIV = DIV_2 // System PLL Output Clock Divider (2x Divider)
#pragma config UPLLFSEL = FREQ_24MHZ // USB PLL Input Frequency Selection (USB PLL input is 24 MHz)
// DEVCFG1
#pragma config FNOSC = SPLL // Oscillator Selection Bits (Primary Osc (HS,EC))
#pragma config DMTINTV = WIN_127_128 // DMT Count Window Interval (Window/Interval value is 127/128 counter value)
#pragma config FSOSCEN = OFF // Secondary Oscillator Enable (Enable SOSC)
#pragma config IESO = OFF // Internal/External Switch Over (Disabled)
#pragma config POSCMOD = EC // Primary Oscillator Configuration (External clock mode)
#pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection (Clock Switch Disabled, FSCM Disabled)
#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576)
#pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming)
#pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode)
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled)
#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%)
#pragma config DMTCNT = DMT31 // Deadman Timer Count Selection (2^31 (2147483648))
#pragma config FDMTEN = OFF // Deadman Timer Enable (Deadman Timer is disabled)
// DEVCFG0
#pragma config DEBUG = OFF // Background Debugger Enable (Debugger is disabled)
#pragma config JTAGEN = OFF // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
#pragma config TRCEN = ON // Trace Enable (Trace features in the CPU are enabled)
#pragma config BOOTISA = MIPS32 // Boot ISA Selection (Boot code and Exception code is MIPS32)
#pragma config FECCCON = OFF_UNLOCKED // Dynamic Flash ECC Configuration (ECC and Dynamic ECC are disabled (ECCCON bits are writable))
#pragma config FSLEEP = OFF // Flash Sleep Mode (Flash is powered down when the device is in Sleep mode)
#pragma config DBGPER = PG_ALL // Debug Mode CPU Access Permission (Allow CPU access to all permission regions)
#pragma config SMCLR = MCLR_NORM // Soft Master Clear Enable bit (MCLR pin generates a normal system Reset)
#pragma config SOSCGAIN = GAIN_2X // Secondary Oscillator Gain Control bits (2x gain setting)
#pragma config SOSCBOOST = ON // Secondary Oscillator Boost Kick Start Enable bit (Boost the kick start of the oscillator)
#pragma config POSCGAIN = GAIN_2X // Primary Oscillator Gain Control bits (2x gain setting)
#pragma config POSCBOOST = ON // Primary Oscillator Boost Kick Start Enable bit (Boost the kick start of the oscillator)
#pragma config EJTAGBEN = NORMAL // EJTAG Boot (Normal EJTAG functionality)
// DEVCP0
#pragma config CP = OFF // Code Protect (Protection Disabled)

/** VARIABLES *****************************************************************/

/** LOCAL MACROS **************************************************************/
#define SYS_CLK_FREQUENCY (200000000ull) // Fsys = 200 MHz
#define PB3_CLK_FREQUENCY_DIV 20 // Fpb3 = 10 MHz
// I/O Control Register Macros
/// Tri-state functions TRISx
#define TRIS_INPUT 1 // sets direction of corresponding pin to input
#define TRIS_OUTPUT 0 // sets direction of corresponding pin to output
#define LED_OFF 0
#define LED_ON 1
// LED_LED1 (RE3)
//#define LED_LED1 PORTEbits.RE3
#define LED_LED1 LATEbits.LATE3
#define TRIS_LED_LED1 TRISEbits.TRISE3
#define LED_LED1_SET() LATESET = _LATE_LATE3_MASK
#define LED_LED1_CLR() LATECLR = _LATE_LATE3_MASK
#define LED_LED1_INV() LATEINV = _LATE_LATE3_MASK
#define LED1_TOGGLE() LED_LED1_INV()
#define LED1_ON() LED_LED1_CLR()
#define LED1_OFF() LED_LED1_SET()
// LED_LED2 (RE4)
//#define LED_LED2 PORTEbits.RE4
#define LED_LED2 LATEbits.LATE4
#define TRIS_LED_LED2 TRISEbits.TRISE4
#define LED_LED2_SET() LATESET = _LATE_LATE4_MASK
#define LED_LED2_CLR() LATECLR = _LATE_LATE4_MASK
#define LED_LED2_INV() LATEINV = _LATE_LATE4_MASK
#define LED2_TOGGLE() LED_LED2_INV()
#define LED2_ON() LED_LED2_CLR()
#define LED2_OFF() LED_LED2_SET()
// Timer Register Macros
/// TxCON: Type B Timer Control Register
#define TIMER_ENABLE 1
#define TIMER_DISABLE 0
/** LOCAL PROTOTYPES ********************************************************/
void InitializeSystem(void); // Initialize hardware and global variables
/** main() ********************************************************************/
int main(void)
{
InitializeSystem();
while(1);

} // main()
/******************************************************************************
* Function: void InitializeSystem(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This routine takes care of all of the system
* initialization that is required.
*
* Note:
*
*****************************************************************************/
void InitializeSystem(void)
{
// PIC32MZ CPU Speed Optimizations (Cache/Wait States/Peripheral Bus Clks)
// On reset, I+D cache is enabled for max performace setting (write-back with write allocation)
// No wait setting required for main data RAM
// Prefetch-cache: Enable prefetch for PFM (any PFM instructions or data)
PRECONbits.PREFEN = 3;
// Flash PM Wait States: MZ Flash runs at 2 wait states @ 200 MHz
PRECONbits.PFMWS = 2;

// Unlock Sequence normally
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
// Modify PB3DIV
// PBClk3 set to 10 MHz (requires config bits setting: Fsys=200MHz)
//Writes to this register require an unlock sequence. Refer to 42.3.7.2 ?Oscillator Switching Sequence? for details.
PB3DIVbits.PBDIV = (PB3_CLK_FREQUENCY_DIV - 1); // Fpb3=Fsys/20 (200/20=10MHz) Timer increment = 100 ns
// Lock sequence
SYSKEY = 0x33333333;
/* Initialize LED LED1 */
LED_LED1 = LED_OFF;
TRIS_LED_LED1 = TRIS_OUTPUT;
/* Initialize LED LED2 */
LED_LED2 = LED_OFF;
TRIS_LED_LED2 = TRIS_OUTPUT;
/* Initialize Timer 2 Peripheral Settings */
// Turn off the timer
T2CONbits.TON = TIMER_DISABLE;
// Pre-Scale = 1:64 (T2Clk: 156250 Hz)
T2CONbits.TCKPS = 6;
// Set T2 period = 100ms
PR2 = 15624;
// Clear counter
TMR2 = 0;
/* Initialize Timer 2 Interrupt Controller Settings */
// Set the interrupt priority to 4
IPC2bits.T2IP = 4;
// Reset the Timer 2 interrupt flag
IFS0bits.T2IF = 0;
// Enable interrupts from Timer 2
IEC0bits.T2IE = 1;
/* Initialize Timer 4 Peripheral Settings */
// Turn off the timer
T4CONbits.TON = TIMER_DISABLE;
T5CONbits.TON = TIMER_DISABLE;
//connect Timer 4 and 5 to a 32-bit size
T4CONbits.T32 = 1;
// Pre-Scale = 1:64 (T4Clk: 156250 Hz)
T4CONbits.TCKPS = 6;
// Set T4 period = 500ms
PR4 = 78124;
// Clear counter
TMR4 = 0;

/* Initialize Timer 5 Interrupt Controller Settings */
// Set the interrupt priority to 3 and sub priority to 1
IPC6bits.T5IP = 3;
IPC6bits.T5IS = 1;
// Reset the Timer 5 interrupt flag
IFS0bits.T5IF = 0;
// Enable interrupts from Timer 5
IEC0bits.T5IE = 1;

/* Set Interrupt Controller for multi-vector mode */
INTCONSET = _INTCON_MVEC_MASK;

/* Assign PIC32MZ shadow register sets to specific CPU IPLs */
PRISS = 0x76543210;
/* Enable Interrupt Exceptions */
// set the CP0 status IE bit high to turn on interrupts globally
__builtin_enable_interrupts();
/* Enable the peripherals */
T2CONbits.TON = TIMER_ENABLE;
T4CONbits.TON = TIMER_ENABLE;
} // InitializeSystem()
/*****************************************************************************
Function:
void __ISR_AT_VECTOR (_TIMER_2_VECTOR, IPL4SRS) T2Interrupt(void);
Description:
Toggles LED LED1 when the Timer 2 interrupt occurs.
Precondition:
Shadow register sets must be assigned to an IPL (PRISS = 0x76543210;)
Parameters:
None
Returns:
None
***************************************************************************/
void __ISR_AT_VECTOR (_TIMER_2_VECTOR, IPL4SRS) T2Interrupt(void)
{
// Toggle LED LED1
LED1_TOGGLE();
// Reset interrupt flag
IFS0bits.T2IF = 0;
}
/*****************************************************************************
Function:
void __ISR_AT_VECTOR (_TIMER_5_VECTOR, IPL3SRS) T4Interrupt(void);
Description:
Toggles LED LED2 when the Timer 5 interrupt occurs.
Precondition:
Shadow register sets must be assigned to an IPL (PRISS = 0x76543210;)
Parameters:
None
Returns:
None
***************************************************************************/
void __ISR_AT_VECTOR (_TIMER_5_VECTOR, IPL3SRS) T5Interrupt(void)
{
// Toggle LED LED2
LED2_TOGGLE();
// Reset interrupt flag
IFS0bits.T5IF = 0;
}
 
#1
maxruben
Super Member
  • Total Posts : 3371
  • Reward points : 0
  • Joined: 2011/02/22 03:35:11
  • Location: Sweden
  • Status: offline
Re: 32-bit timer period register dependent interrupt functionality 2019/10/08 12:15:50 (permalink) ☼ Best Answerby SEY 2019/10/09 12:35:06
5 (2)
Avoid using the method register.bit=value on pic32. This is not an atomic operation and if it is broken by a context switch you could end up setting or resettning wrong bits in the register. This is especially true for interrupt flags sharing the same register (like IFS0). Use SET/CLR/INV with a mask instead.
 
/Ruben
#2
betta.sharma
New Member
  • Total Posts : 11
  • Reward points : 0
  • Joined: 2019/05/28 11:08:17
  • Location: 0
  • Status: offline
Re: 32-bit timer period register dependent interrupt functionality 2019/11/12 18:34:34 (permalink)
0
I have a problem with Timer2 interrupts and want to know if anyone else has seen it.
 
This is the problem reduced to basics:
 
I have a Timer2 Interrupt service routine that gets called on Period Register match. The interrupt service routine gets called as expected if i call sleep() after loading new value into Period Register. However, if the cpu is busy (say in a busy loop), most of the Timer 2 interrupts are "lost" i.e. ISR does not get called as many times.  Somehow, the Timer2 interrupts seem to be occurring only if the CPU is "idle" (I think it executes WAIT instruction for that). If the CPU is never idle, interrupts don't seem to happen. Has anyone seen this or similar behavior (interrupts lost when CPU is busy)?
#3
Jump to:
© 2019 APG vNext Commercial Version 4.5