Dear all,
I am confused with how project with mixed C and assembly is handled in Microchip C30. I have a very simple project that uses TMR1 interrupt to toggle an LED. I tried this project on dsPIC3312GP202 which is used in Microchip 16-bit 28-pin Starter kit.
I have a project that contains two files, one coded with C language and the other one coded in assembly. The C listing is as follows (main.c)
#include "P33FJ12GP202.h"
/*
* Internal FRC Oscillator
*
*/
_FOSCSEL(FNOSC_FRC);
/*
* Clock switching is enabled and fail-safe clock monitor is disabled
* OSC2 pin function: OSC2 is clock output
* Primary oscillator mode is disabled
*
*/
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_NONE);
/*
* Watchdog timer is disabled
*
*/
_FWDT(FWDTEN_OFF);
/*
* Function prototypes
*
*/
void initialisePorts( void );
void initialiseTimer1( void );
void performClockSwitching( void );
/*
* Main program entry
*
*/
int main( void ) {
/*
* Initialise clock-switching
*
*/
performClockSwitching();
/*
* Initialise port direction and value
*
*/
initialisePorts();
/*
* Initialise Timer1
*
*/
initialiseTimer1();
/*
* Loop here doing nothing - waiting for Timer1 interrupt to occur
*
*/
while (1) {
}
return 0;
}
/*
* Initialise input and output ports
*
*/
void initialisePorts( void ) {
/*
* At the moment we are only interested in port B, where
* o Pin 5 - incoming data
* o Pin 6 - re-timed data
* o Pin 10 - recovered clock
* o Pin 12 - LED4
* o Pin 13 - LED3
* o Pin 14 - LED2
* o Pin 15 - LED1
*
* Note 0 - output, 1 - input
*
*/
TRISB = 0b0000101110111111;
/*
* Initial value of port B
*
*/
LATB = 0xF000;
}
/*
* Initialise Timer1
* Interrupt Service Routine will be called when Timer1 overflows
*
*/
void initialiseTimer1( void ) {
TMR1 = 0x00;
PR1 = 53; /* timer preload value */
/*
* T1CON register
*
* bit | Value | Description
* -----+-------+--------------------------------------
* 15 | 1 | TON - enable Timer1
* 14 | 0 | Reserved
* 13 | 0 | TSIDL - Not stop in idle mode
* 12-7 |000000 | Reserved
* 6 | 0 | TSYNC - sync to ext. clock disabled
* 5-4 | 00 | TCKPS - prescaler of 1:1
* 3-2 | 00 | Reserved
* 1 | 0 | TCS - Internal clock as source
* 0 | 0 | Reserved
*
*/
T1CON = 0b1000000000000000;
/*
* Set Timer1 interrupt priority
*
*/
IPC0 &= 0x0FFF;
IPC0 ^= 0x1000;
/*
* Clear Timer1 interrupt flag and enable Timer1
*
*/
IFS0bits.T1IF = 0;
IEC0bits.T1IE = 1;
}
/*
* Perform clock switching
*
*/
void performClockSwitching( void ) {
OSCTUN = 0; /* Tune FRC oscillator, if FRC is used */
/*
* Configure oscillator to operate the device at Fcy = 40Mhz
* Fosc = Fin*M/(N1*N2)
* Fcy = Fosc/2
* Fosc = 7.37Mhz * 43/(2 * 2) = 80MHz for 7.37MHz input clock
*
*/
PLLFBD = 43; /* M = 43 */
CLKDIVbits.PLLPOST = 0; /* N1 = 2 */
CLKDIVbits.PLLPRE = 0; /* N2 = 2 */
/*
* Disable Watch Dog Timer
*
*/
RCONbits.SWDTEN = 0;
/*
* Initiate clock switch to FRC with PLL
* NOSC = 0b001
*
*/
__builtin_write_OSCCONH(0b001);
/*
* Start clock switching
*
*/
__builtin_write_OSCCONL(0b001);
/*
* Wait for clock switch to occur
*
*/
while (OSCCONbits.COSC != 0b001)
/*
* Wait for PLL to lock
*
*/
while(OSCCONbits.LOCK!=1) {};
}
The assembly listing (T1Interrupt.s) contains the ISR of TMR1. All it does is to clear TMR1 interrupt flag and toggle an LED. The listing is as follows
.text
.include "p33FJ12GP202.inc"
;--------------------------------------------------------------------
; T1Interrupt - ISR of Timer1
;
;--------------------------------------------------------------------
__T1Interrupt:
bclr IFS0, #T1IF ; clear interrupt flag
btg PORTB, #15
retfie ; Return from interrupt
.end
I built the project and then programmed with using RealICE to my starter kit. Everytime when I ran this project, it would be halted almost immediately.
However, instead of coding TMR1 ISR in assembly, if I added the following code to main.c and remove T1Interrupt.s from the project, the project ran perfectly.
void __attribute__((__interrupt__)) __attribute__((no_auto_psv)) _T1Interrupt( void )
{
LATB ^= 0x8000;
/* reset Timer 1 interrupt flag */
IFS0bits.T1IF = 0;
}
Any idea why?
I look forward to hearing your feedback.
Thanks
dsPICgy