• AVR Freaks

LockedHot!Accessing Core Timer on PIC32MM

Author
btremaine
Junior Member
  • Total Posts : 59
  • Reward points : 0
  • Joined: 2013/08/17 14:46:34
  • Location: San Jose, CA
  • Status: offline
2019/12/09 13:03:22 (permalink)
0

Accessing Core Timer on PIC32MM

Hi,
My overall goal for now is to prove to myself the Core Timer is available on the PIC32MM0064GPL036 part.
I wrote the following code and made use of the mfc0 and mft0 assembly commands. However I never get a core timer vector interrupt.
I'm running this on the Curiosity board for the part in question and am turning on LED2 and trying to toggle LED1 twice per second. I am trying to do this without use of the peripheral library or Harmony to keep it simple.
 
At this point I don't know if
1) The mfc0 / mft0 commands are wrong, or
2) My interrupt is set up wrong, or
3) I'm overlooking something, or
4) The PIC32MM part does not have access to the core timer.
 
Can someone look this over and give me some pointers please ? I have gotten help to get this far and appreciate it very much.
 

 
// Necessary include files
#include <xc.h> // automatically includes <cp0defs.h>
#include <sys/attribs.h>
#include <stdbool.h>
#include <math.h>

// #pragma config included in system.c()

// Let compile time pre-processor calculate the CORE_TICK_PERIOD
#define SYS_FREQ (24000000L)
#define TOGGLES_PER_SEC 2
#define CORE_TICK_RATE (SYS_FREQ/2/TOGGLES_PER_SEC)

#define LED1_PORT PORTAbits.RA0
#define LED2_PORT PORTCbits.RC9
//
#define LED1_LAT LATAbits.LATA0
#define LED2_LAT LATCbits.LATC9
//
#define LED1_TRIS TRISAbits.TRISA0
#define LED2_TRIS TRISCbits.TRISC9

volatile uint32_t coretimer = 0;
volatile uint32_t core_tick_rate = CORE_TICK_RATE;
volatile uint32_t reg_32bit;

// timer_interrupt application
int main(void)
{
SYSTEM_Initialize();

// enable LED1 & LED2
LED1_TRIS = 0;
LED2_TRIS = 0;
LED1_PORT = 0;
LED2_PORT = 0;

// configure the core timer roll-over rate (100msec)
Nop();
asm volatile("mtc0 %0,$11" : "+r" (core_tick_rate)); // set compare register

// set up the core timer interrupt with a priority of 2, zero sub-priority,
// and enable
#define CT_INT_ON (1<<15)
#define CT_INT_PRIOR_2 (2)
#define CT_INT_SUB_PRIOR_0 (0<<4)

reg_32bit = (CT_INT_ON | CT_INT_PRIOR_2 | CT_INT_SUB_PRIOR_0) ;
asm volatile("mtc0 %0,$12" : "+r" (reg_32bit)) ;

// enable device multi-vector interrupts
INTCONbits.MVEC=1;

// configure LED1 and LED2 as outputs
LED1_TRIS = 0;
LED2_TRIS = 0;

LED2_LAT = 1; // turn on LED2

__builtin_enable_interrupts();

while(1);

}

// needs <sys/attribs.h>
void __ISR(_CORE_TIMER_VECTOR, IPL2SOFT) CoreTimerHandler(void)
{
// do your thing ...

// .. Toggle the LED
LED1_LAT ^= 1;

// clear the interrupt flag
IFS0CLR = _IFS0_CTIF_MASK; /* Clear the interrupt flag */
}

 
post edited by btremaine - 2019/12/09 13:32:12
#1

3 Replies Related Threads

    simong123
    Lab Member No. 003
    • Total Posts : 1391
    • Reward points : 0
    • Joined: 2012/02/07 18:21:03
    • Location: Future Gadget Lab (UK Branch)
    • Status: offline
    Re: Accessing Core Timer on PIC32MM 2019/12/09 20:02:42 (permalink)
    +3 (3)
    I don't understand what you are trying to achieve with this:-
    // set up the core timer interrupt with a priority of 2, zero sub-priority,
    // and enable
    #define CT_INT_ON (1<<15)
    #define CT_INT_PRIOR_2 (2)
    #define CT_INT_SUB_PRIOR_0 (0<<4)

    reg_32bit = (CT_INT_ON | CT_INT_PRIOR_2 | CT_INT_SUB_PRIOR_0) ;
    asm volatile("mtc0 %0,$12" : "+r" (reg_32bit)) ;

    As written you are trying to set CP0 register 12 select 0 (the Status register) to 0x8002.
    Not a good thing to do!(™)
     
    To set up the core timer interrupt use
    IPC0bits.CTIP=2; //Core Timer Priority 2
    IPC0bits.CTIS=0; //Core Timer Sub Priority 0
    IEC0bits.CTIE=1; // Core Timer Interrupt Enable

     
    To read the core timer you can use the _mfc0() macro from xc.h
    uint32_t timer_value=_mfc0(9,0);

    To set the compare register use the _mtc0() macro:-
    _mtc0(11,0,compare_val);

     
    Note the core timer is a free running counter. The interrupt fires whenever the count and compare values are equal. You cannot set a 'rate', you have to either clear the count register or calculate a new value for the compare register in the interrupt.
    #2
    NKurzman
    A Guy on the Net
    • Total Posts : 18898
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: online
    Re: Accessing Core Timer on PIC32MM 2019/12/09 22:00:42 (permalink)
    +1 (1)
    Note:
    _CP0_GET_COUNT()
    This macro Will also read the core timer.
    It is part of XC32
    #3
    btremaine
    Junior Member
    • Total Posts : 59
    • Reward points : 0
    • Joined: 2013/08/17 14:46:34
    • Location: San Jose, CA
    • Status: offline
    Re: Accessing Core Timer on PIC32MM 2019/12/10 06:57:05 (permalink)
    0
    Thanks! I realized later after I posted this I was using the FRM for CPU devices using the M4 core. I later found the CPU FRM for the PIC32MM which uses the microAptiv core, they are different. I still had some problems so I will take a close look at your suggestions. Thank you very much for the input.
     
    When I get it working I will post my solution .....
     
    ........ adding edits after reviewing the useful suggestions from simong123
    I incorporated the _mfc0 and _mtc0 macros and corrected the settings of the ICP0bits for the PIC32MM core.
    I also modified the ISR to read the coretimer and set the new core compare value to give the interrupt period I'm looking for. Using the PIC32MM Curisosity Board the SYSCLK is 8.000MHz. Using this clock the interrupt period is set to 1.00 seconds to toggle LED1. LED2 is toggled in the while() loop and the period is 5us. 
     
    This accomplished what I wanted to find out. I can use the 1 MCCP and 2 SCCP for my control of a BLDC motor and still have an additional timer (the free-running core timer) to use elsewhere. 
     
    Thanks for your input simong123, ;)
     
    // Necessary include files
    #include <xc.h> // automatically includes <cp0defs.h>
    #include <sys/attribs.h>
    #include <stdbool.h>
    #include <math.h>

    // #pragma config included in system.c()

    // Let compile time pre-processor calculate the CORE_TICK_PERIOD
    #define SYS_FREQ (8000000L)
    #define TOGGLES_PER_SEC 2
    #define CORE_TICK_VALUE (SYS_FREQ/1/TOGGLES_PER_SEC)

    #define LED1_PORT PORTAbits.RA0
    #define LED2_PORT PORTCbits.RC9
    //
    #define LED1_LAT LATAbits.LATA0
    #define LED2_LAT LATCbits.LATC9
    //
    #define LED1_TRIS TRISAbits.TRISA0
    #define LED2_TRIS TRISCbits.TRISC9

    volatile uint32_t coretimer = 0;
    volatile uint32_t core_tick_value = CORE_TICK_VALUE;
    volatile uint32_t reg_32bit;

    // timer_interrupt application
    int main(void)
    {
        SYSTEM_Initialize();
        
        // enable LED1 & LED2
        LED1_TRIS = 0;
        LED2_TRIS = 0;
        LED1_PORT = 0;
        LED2_PORT = 0;
        
        // configure the core timer value (100ms)
        // compare register, 'select'0
        _mtc0(11,0,core_tick_value);
        
        // set up the core timer interrupt with a priority of 2, zero sub-priority,
        // and enable
        
        IPC0bits.CTIP=2; //Core Timer Priority 2
        IPC0bits.CTIS=0; //Core Timer Sub Priority 0
        IEC0bits.CTIE=1; // Core Timer Interrupt Enable

        // enable device multi-vector interrupts
        INTCONbits.MVEC=1;

     // configure LED1 and LED2 as outputs
        LED1_TRIS = 0;
        LED2_TRIS = 0;
        LED2_LAT = 1; // turn on LED2
       
        __builtin_enable_interrupts();

        while(1){
           uint32_t timer_value= _mfc0(9,0);
           LED2_LAT ^= 1; // (5us))
            
        }

    }

    // needs <sys/attribs.h>
    void __ISR(_CORE_TIMER_VECTOR, IPL2SOFT) CoreTimerHandler(void)
    {
        // do your thing ...
     // .. Toggle the LED
        LED1_LAT ^= 1;
        
        uint32_t coretimer = _mfc0(9,0);
        uint32_t timer_compare = coretimer + core_tick_value;
        // reset core timer
        _mtc0(11,0,timer_compare);

        // clear the interrupt flag
        IFS0CLR = _IFS0_CTIF_MASK; /* Clear the interrupt flag */
    }

    post edited by btremaine - 2019/12/10 09:27:49
    #4
    Jump to:
    © 2020 APG vNext Commercial Version 4.5