CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Issue PIC24FJ256GB110 irq Serial1 (#INT_RDA) Freez system
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ciccioc74



Joined: 23 Mar 2010
Posts: 44

View user's profile Send private message Visit poster's website MSN Messenger

PostPosted: Thu Feb 13, 2025 3:41 am     Reply with quote

Quote:
This is why I prefer to give UART streams names that correspond to the
physical UART they use, so you 'know' which port is involved.

sorry could you give me an example?
Ttelmah



Joined: 11 Mar 2010
Posts: 19926

View user's profile Send private message

PostPosted: Thu Feb 13, 2025 6:39 am     Reply with quote

So the stream that connects to the RS485, and uses UART4, call something
line RS485_U4. Then the handler is for INT_RDA4. If you change to using
a different UART, change the stream name to correspond to what UART it
uses, and any discrepancy becomes obvious.
I suspect you are actually reading the wrong UART in one of your interrupt
handlers, and hence the lockup.
ciccioc74



Joined: 23 Mar 2010
Posts: 44

View user's profile Send private message Visit poster's website MSN Messenger

PostPosted: Thu Mar 13, 2025 11:53 am     Reply with quote

I had set aside the bootloader issue to focus on other things, but now I'd like to understand where the problem is. Analyzing the .lst file, I noticed that something doesn't add up. Could you help me figure out what's wrong?
Code:

CCS PCD C Compiler, Version 5.119d, 1               13-mar-25 18:38
Compiler operating in Evaluation Mode
To obtain a fully enabled compiler visit www.ccsinfo.com/products

in the ISR timer2:
Code:
................... #INT_TIMER2
.................... void my_timer2_isr (){ 
*
019FC:  PUSH    42
019FE:  PUSH    36
01A00:  PUSH    32
01A02:  MOV     W0,[W15++]
01A04:  MOV     #2,W0
01A06:  REPEAT  #C
01A08:  MOV     [W0++],[W15++]
....................   if(++cont_1s>100){//0,5 seconds
01A0A:  INC     0802
01A0C:  MOV     802,W4
01A0E:  MOV     #64,W3
01A10:  CP      W3,W4
01A12:  BRA     GE,1A1A
....................     cont_1s=0;   
01A14:  CLR     802
....................     output_toggle(PIN_D15);   
01A16:  BCLR.B  2D9.7
01A18:  BTG.B   2DD.7
....................   }
.................... }
01A1A:  BCLR.B  84.7
01A1C:  MOV     #1A,W0
01A1E:  REPEAT  #C
01A20:  MOV     [--W15],[W0--]
01A22:  MOV     [--W15],W0
01A24:  POP     32
01A26:  POP     36
01A28:  POP     42
01A2A:  RETFIE 

focus on the line :01A1A: BCLR.B 84.7
in the ISR USART3:
Code:
.................... #INT_RDA3
.................... void  myRXisr(){ 
*
01A3A:  PUSH    42
01A3C:  PUSH    36
01A3E:  PUSH    32
01A40:  MOV     W0,[W15++]
01A42:  MOV     #2,W0
01A44:  REPEAT  #C
01A46:  MOV     [W0++],[W15++]
....................     U3RXIF=0;
01A48:  BCLR.B  8E.2
....................     do{
....................        temp= fgetc(UART3);
01A4A:  CALL    1A2C
01A4E:  MOV.B   W0L,804
01A50:  CLR.B   805
....................        output_toggle(LED3);       
01A52:  BCLR.B  2D1.5
01A54:  BTG.B   2D5.5
....................     } while (kbhit(UART3));
01A56:  BTSC.B  252.0
01A58:  BRA     1A4A
.................... }
01A5A:  BCLR.B  8E.2
01A5C:  MOV     #1A,W0
01A5E:  REPEAT  #C
01A60:  MOV     [--W15],[W0--]
01A62:  MOV     [--W15],W0
01A64:  POP     32
01A66:  POP     36
01A68:  POP     42
01A6A:  RETFIE 

focus on the 01A5A: BCLR.B 8E.2
but on the interrupt of serial4:
Code:

.................... #INT_RDA4
.................... void  myRXisr485(){   
01A6C:  PUSH    42
01A6E:  PUSH    36
01A70:  PUSH    32
01A72:  MOV     W0,[W15++]
01A74:  MOV     #2,W0
01A76:  REPEAT  #C
01A78:  MOV     [W0++],[W15++]
....................     U4RXIF=0;
01A7A:  BCLR.B  8F.0
.................... //    do{
.................... //       temp= fgetc(UART4);
.................... //       output_toggle(LED4);       
.................... //    } while (kbhit(UART4));       
.................... }
....................
01A7C:  BCLR.B  8F.0
01A7E:  MOV     #1A,W0
01A80:  REPEAT  #C
01A82:  MOV     [--W15],[W0--]
01A84:  MOV     [--W15],W0
01A86:  POP     32
01A88:  POP     36
01A8A:  POP     42
01A8C:  RETFIE 

the line 01A7C: BCLR.B 8F.0 clear 8F.0 bit but U4RXIF is located at 8E.8. could you explain to me why?
Ttelmah



Joined: 11 Mar 2010
Posts: 19926

View user's profile Send private message

PostPosted: Fri Mar 14, 2025 2:24 am     Reply with quote

16bit registers........

0x8e, if accessed as a 16bit register has bit 8 as U4RXIF. However you can
also perform an _8bit_ access to the next address up to access the same
bit.

BCLR.W 8E.8 == BCLR.B 8F.0 ***** not actually possible see below.

The data sheet describes the registers with 16bit values and addresses.
However the code to talk to the bit set/reset, uses 8bit addressing and
values.
The reason is that the BLCR.W version, can only be used on a W reg,
not on any memory address. So to do the same with word addressing,
you would have to read the 16bit word into a W reg, then use BCLR.W
on this register, and then write this back. Three instructions, where the bit
addresed 'byte' version does it in one.
ciccioc74



Joined: 23 Mar 2010
Posts: 44

View user's profile Send private message Visit poster's website MSN Messenger

PostPosted: Fri Mar 14, 2025 2:43 am     Reply with quote

Ok. Thank.
ciccioc74



Joined: 23 Mar 2010
Posts: 44

View user's profile Send private message Visit poster's website MSN Messenger

PostPosted: Wed Aug 13, 2025 7:46 am     Reply with quote

I need to get back to working on the bootloader issue.
Please let me know if I can continue on this thread or if I should start a new one.

I also opened a support ticket with Microchip to ask about the reliability of their bootloader, and they suggested I replicate the basic program using their compiler. The result: it works. The same program compiled with the CCS compiler freezes at receive of one byte on UART4.
Code:


#ZERO_RAM
#include <24FJ256GB110.h>
#device ADC=10
#device ICSP=2

//#define BOOTLOADER

#ifdef BOOTLOADER

// Bootloader
#define LOADER_START                (0)
#define LOADER_END                  (0x1600+0x400-1)
#define LOADER_SIZE                 (LOADER_END - LOADER_START + 1)

// Applicazione
#define APPLICATION_START           (0x1600+0x400)
#define APPLICATION_ISR             (0x1600+0x400+4)  // posizione del primo vettore interrupt
#define APPLICATION_END             (getenv("PROGRAM_MEMORY") - 1)

// Costringe CCS a compilare codice da 0x1800 in poi
#BUILD(RESET=APPLICATION_START, INTERRUPT=APPLICATION_ISR)

// Riserva lo spazio del bootloader per evitare che CCS lo tocchi
#org LOADER_START, LOADER_END {}

    #fuses NONE
    #use delay(clock=32000000)
#else

    #FUSES NODEBUG                 
    #FUSES ICSP1                   
    #FUSES NOWINDIS
    #FUSES WPOSTS16                 
    #FUSES IESO                     
    #FUSES NOCKSFSM                 
    #FUSES NOOSCIO                 
    #FUSES HS                       
    #FUSES NOIOL1WAY
    #FUSES NOWPCFG               
    #FUSES NOWPDIS 
    #FUSES PR_PLL                   
    #FUSES PLL3                 
    #FUSES RESERVED                 
    #FUSES DISUVREG
    #use delay(clock=32000000,crystal=8000000)
#endif

#pin_select U4TX=PIN_G6
#pin_select U4RX=PIN_G8
#use rs232(UART4, baud=9600, errors, stream=COMREM)

#pin_select U3TX=PIN_D10
#pin_select U3RX=PIN_D11
#use rs232(UART3, baud=115200, errors, stream=ESP)


#pin_select INT1 = PIN_C3
#pin_select INT2 = PIN_C2

#define LED3   PIN_C13
#define LED4   PIN_C14

#define K2   PIN_D15
#define K3   PIN_D14
#define K4   PIN_B15
#define K5   PIN_B14
#define K6   PIN_B13
#define K7   PIN_B12

//#priority INT_RDA, INT_RDA2,INT_EXT1,INT_EXT2,  INT_TIMER2

int cont_1s=0;
volatile int temp;

#INT_TIMER2
void my_timer2_isr (){  //timer a 125msecondi 
  clear_interrupt(INT_TIMER2);
  if(++cont_1s>70){//0,5 seconds
    cont_1s=0;   
    output_toggle(K2);   
  }   
}

#INT_RDA4
void  myRXisr485(){ 
    clear_interrupt(INT_RDA4);
    do{
       temp= fgetc(COMREM);
       //temp = U4RXREG;
       output_toggle(K4);       
    } while (kbhit(COMREM));   
}

#INT_RDA3
void  myRXisrESP(){   
   clear_interrupt(INT_RDA3);
    do{
       temp= fgetc(ESP);
       output_toggle(K3);       
    } while (kbhit(ESP));
}


#INT_EXT1
void ext1IRQ(){
  output_toggle(K5);
}

#INT_EXT2
void ext2IRQ(){
   output_toggle(K7);
}

void disableAllIRQ(){
disable_interrupts( INT_EXT0);//6
disable_interrupts( INT_IC1);// 7
disable_interrupts( INT_OC1);// 8
disable_interrupts( INT_TIMER1 );// 9
disable_interrupts( INT_IC2);// 70
disable_interrupts( INT_OC2);// 71
disable_interrupts( INT_TIMER2);//72
disable_interrupts( INT_TIMER3);//73
disable_interrupts( INT_SPI1E);//74
disable_interrupts( INT_SPI1);//75
disable_interrupts( INT_RDA);// 76
disable_interrupts( INT_TBE);// 77
disable_interrupts( INT_ADC1);//78
disable_interrupts( INT_SI2C);//81
disable_interrupts( INT_MI2C);//82
disable_interrupts( INT_CNI);// 84
disable_interrupts( INT_EXT1);//85
disable_interrupts( INT_IC7);// 87
disable_interrupts( INT_IC8);// 88
disable_interrupts( INT_OC3);// 90
disable_interrupts( INT_OC4);// 91
disable_interrupts( INT_TIMER4);//92
disable_interrupts( INT_TIMER5);// 93
disable_interrupts( INT_EXT2);//94
disable_interrupts( INT_RDA2);//95
disable_interrupts( INT_TBE2);//96
disable_interrupts( INT_SPI2E);//97
disable_interrupts( INT_SPI2);//98
disable_interrupts( INT_IC3);// 102
disable_interrupts( INT_IC4);// 103
disable_interrupts( INT_IC5);// 104
disable_interrupts( INT_IC6);// 105
disable_interrupts( INT_OC5);// 106
disable_interrupts( INT_OC6);// 107
disable_interrupts( INT_OC7);// 108
disable_interrupts( INT_OC8);// 109
disable_interrupts( INT_SI2C2);//114
disable_interrupts( INT_MI2C2);//115
disable_interrupts( INT_EXT3);//118
disable_interrupts( INT_EXT4);//119
disable_interrupts( INT_UART1E);//130
disable_interrupts( INT_UART2E);//131
disable_interrupts( INT_SPI3);//137
disable_interrupts( INT_UART3E);//141
disable_interrupts( INT_RDA3);//142
disable_interrupts( INT_TBE3);//143
disable_interrupts( INT_UART4E);//144
disable_interrupts( INT_RDA4);//145
disable_interrupts( INT_TBE4);//146
disable_interrupts( INT_USB);// 147
disable_interrupts( INT_SI2C3);//148
disable_interrupts( INT_MI2C3);//149
disable_interrupts( INT_COMP);//152
disable_interrupts( INT_OC9);// 162
disable_interrupts( INT_IC9);// 163
disable_interrupts( INT_PMP);// 164
disable_interrupts( INT_SPI3E);//172
disable_interrupts( INT_RTC);// 173
disable_interrupts( INT_CRC);// 174
disable_interrupts( INT_CTMU);//176
disable_interrupts( INT_LVD);// 179

}
void main()   {
    //ALTIVT =1;
   
    int cont=0,i=0;
    disableAllIRQ();
    disable_interrupts(0x0800);     
    output_a(0);
    set_tris_a (0b0000000000000000);
    output_b(0);
    set_tris_b (0b0000001100101111);
    set_pulldown(1, PIN_B0);     //per il galleggiante ho bisogno di un pull down
    set_pulldown(1, PIN_B1);   
    //set_pullup(TRUE,PIN_B0);
    //set_pulldown(TRUE, PIN_B1);
    output_c(0);
    set_tris_c (0b0000000000001110);
    output_d(0);
    set_tris_d (0b0000100001001100);
    output_e(0);
    set_tris_e(0);
    output_f(0);
    set_tris_f(0xffff);
    output_g(0);
    set_tris_g (0b0000000100000000);
    output_low(PIN_G7);//enab         
    output_float(PIN_A2);
    output_float(PIN_A3);
   
    enable_interrupts(INT_EXT1);
    enable_interrupts(INT_EXT2);
    setup_timer2(TMR_INTERNAL | TMR_DIV_BY_64, 1249);
    enable_interrupts(INT_TIMER2);
    enable_interrupts(INT_RDA3); 
    enable_interrupts(INT_RDA4); 
    for( i=0;i<5;i++){
        output_toggle(K6);
        delay_ms(200);
    }
    enable_interrupts(0x0800);
    while(1){
    output_low(PIN_G7);
        delay_ms(500);
        output_toggle(K6);
        //if( cont++>3)
        //enable_interrupts(0x0800);   
    }
}


XC16 compiler:
Code:
#include <xc.h>
#include <p24fj256gb110.h> // Assicurati che questo header sia corretto per il tuo PIC specifico
#define FCY 32000000UL     // Definisce FCY per __delay_ms

#include <libpic30.h>
#include <stdint.h>


// CONFIG BITS copied from USB_Device_Bootloader project.

/** CONFIGURATION Bits **********************************************/
// CONFIG3
#pragma config WPFP = WPFP511           // Write Protection Flash Page Segment Boundary (Highest Page (same as page 170))
#pragma config WPDIS = WPDIS            // Segment Write Protection Disable bit (Segmented code protection disabled)
#pragma config WPCFG = WPCFGDIS         // Configuration Word Code Page Protection Select bit (Last page(at the top of program memory) and Flash configuration words are not protected)
#pragma config WPEND = WPENDMEM         // Segment Write Protection End Page Select bit (Write Protect from WPFP to the last page of memory)

// CONFIG2
#pragma config POSCMOD = HS             // Primary Oscillator Select (HS oscillator mode selected)
#pragma config DISUVREG = ON//ciccio OFF           // Internal USB 3.3V Regulator Disable bit (Regulator is disabled)
#pragma config IOL1WAY = OFF//ciccio ON             // IOLOCK One-Way Set Enable bit (Write RP Registers Once)
#pragma config OSCIOFNC = ON            // Primary Oscillator Output Function (OSCO functions as port I/O (RC15))
#pragma config FCKSM = CSDCMD           // Clock Switching and Monitor (Both Clock Switching and Fail-safe Clock Monitor are disabled)
#pragma config FNOSC = PRIPLL           // Oscillator Select (Primary oscillator (XT, HS, EC) with PLL module (XTPLL,HSPLL, ECPLL))
#pragma config PLL_96MHZ = ON           // 96MHz PLL Disable (Enabled)
#pragma config PLLDIV = DIV2            // USB 96 MHz PLL Prescaler Select bits (Oscillator input divided by 2 (8MHz input))
#pragma config IESO = OFF               // Internal External Switch Over Mode (IESO mode (Two-speed start-up)disabled)

// CONFIG1
#pragma config WDTPS = PS32768          // Watchdog Timer Postscaler (1:32,768)
#pragma config FWPSA = PR128            // WDT Prescaler (Prescaler ratio of 1:128)
#pragma config WINDIS = OFF             // Watchdog Timer Window (Standard Watchdog Timer enabled,(Windowed-mode is disabled))
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (Watchdog Timer is disabled)
#pragma config ICS = PGx2               // Comm Channel Select (Emulator functions are shared with PGEC2/PGED2)
#pragma config GWRP = OFF               // General Code Segment Write Protect (Writes to program memory are allowed)
#pragma config GCP = OFF                // General Code Segment Code Protect (Code protection is disabled)
#pragma config JTAGEN = OFF             // JTAG Port Enable (JTAG port is disabled)





// LED 5..9 on EXPLORER 16/32 board + PIC24FJ256GB110
#define LED1 LATDbits.LATD15
#define LED1_TOGGLE() (LED1 = !LED1)
#define LED2 LATDbits.LATD14
#define LED2_TOGGLE() (LED2 = !LED2)
#define LED3 LATBbits.LATB15
#define LED3_TOGGLE() (LED3 = !LED3)
#define LED4 LATBbits.LATB14
#define LED4_TOGGLE() (LED4 = !LED4)
#define LED5 LATBbits.LATB13
#define LED5_TOGGLE() (LED5 = !LED5)
#define LED6 LATBbits.LATB12
#define LED6_TOGGLE() (LED6 = !LED6)
#define ENAB LATGbits.LATG7

#define RX_BUFFER_SIZE 64


// === Variabili globali ===
volatile uint16_t tickCount = 0;
volatile char rxBuffer[RX_BUFFER_SIZE];
volatile uint8_t rxHead = 0, rxTail = 0;

// === Interrupt Timer1 ===
void __attribute__((__interrupt__, __no_auto_psv__)) _T1Interrupt(void) {
    IFS0bits.T1IF = 0; // Pulisci il flag

    tickCount++;
    if (tickCount >= 100) { // ogni 100 * 10ms = 1 secondo
       LED1_TOGGLE();
        tickCount = 0;
    }
}

// === ISR: lampeggia LED2 ogni volta che arriva un byte 485 ===
void __attribute__((__interrupt__, __no_auto_psv__)) _U4RXInterrupt(void) {
    volatile char dummy;
    IFS5bits.U4RXIF = 0;

    if (U4STAbits.FERR || U4STAbits.OERR) {
        dummy = U4RXREG;
        U4STAbits.OERR = 0;
        return;
    }
    volatile char c = U4RXREG; // Leggi il byte ricevuto
    LED2_TOGGLE();              // Lampeggia LED2
}

// === ISR: lampeggia LED3 ogni volta che arriva un byte  esp32 ===
void __attribute__((__interrupt__, __no_auto_psv__)) _U3RXInterrupt(void){//
    volatile char dummy;
    IFS5bits.U3RXIF = 0;          // clear flag

    // gestisci errori
    if (U3STAbits.FERR || U3STAbits.OERR) {
        dummy = U3RXREG;          // svuota
        U3STAbits.OERR = 0;
        return;
    }
    volatile char c = U3RXREG;    // leggi byte
    LED3_TOGGLE();                // feedback (come per U4)
    // TODO: copia in buffer circolare se serve
}
void __attribute__((__interrupt__, __no_auto_psv__)) _INT1Interrupt(void)
{//
    IFS1bits.INT1IF = 0;   // clear flag
    LED4_TOGGLE();         // toggle LED4 su INT1 (RC3)
}

void __attribute__((__interrupt__, __no_auto_psv__)) _INT2Interrupt(void)
{//
    IFS1bits.INT2IF = 0;   // clear flag
    LED5_TOGGLE();         // toggle LED5 su INT2 (RC2)
}


void ConfigurePLL(void) {
    CLKDIV = 0x1E00; // PLLPRE=0, PLLPOST=0, PLLFBD=30 (Fosc = 64MHz)

    __builtin_write_OSCCONH(0x03);         // Seleziona PRIPLL
    __builtin_write_OSCCONL(OSCCON | 0x01); // Avvia il cambio

    while (OSCCONbits.COSC != 0b011); // Attendi che il cambio avvenga
    while (OSCCONbits.LOCK != 1);     // Attendi il lock del PLL

    CLKDIVbits.DOZEN = 0; // Disattiva riduzione FCY!
}

void ConfigureUART4Pins(void) {//485
      __builtin_write_OSCCONL(OSCCON & ~(1 << 6));    // unlock PPS

    // U4TX -> RP21 (RG6)   [U4TX output function = 30]
    RPOR10bits.RP21R = 30;

    // U4RX <- RP19 (RG8)
    RPINR27bits.U4RXR = 19;

    __builtin_write_OSCCONL(OSCCON |  (1 << 6));    // lock PPS

    // direzione pin
    TRISGbits.TRISG6 = 0;   // TX out
    TRISGbits.TRISG8 = 1;   // RX in

}

void ConfigureUART3Pins(void)
{//
    // RD10 -> RP3 (U3TX), RD11 -> RP12 (U3RX)
    __builtin_write_OSCCONL(OSCCON & ~(1 << 6));   // unlock PPS

    RPOR1bits.RP3R   = 28;   // U3TX -> RP3 (RD10)   (28 = U3TX)
    RPINR17bits.U3RXR = 12;  // U3RX <- RP12 (RD11)

    __builtin_write_OSCCONL(OSCCON |  (1 << 6));   // lock PPS

    // Direzioni pin (consigliato)
    TRISDbits.TRISD10 = 0;   // TX out
    TRISDbits.TRISD11 = 1;   // RX in
}
void ConfigureExternalINTs(void)
{//
    // RC3 = RPI40 -> INT1, RC2 = RPI39 -> INT2
    __builtin_write_OSCCONL(OSCCON & ~(1 << 6));   // unlock PPS
    RPINR0bits.INT1R = 40;   // INT1 <- RPI40 (RC3)
    RPINR1bits.INT2R = 39;   // INT2 <- RPI39 (RC2)
    __builtin_write_OSCCONL(OSCCON |  (1 << 6));   // lock PPS

    // direzione pin (ingresso)
    TRISCbits.TRISC3 = 1;    // RC3 input
    TRISCbits.TRISC2 = 1;    // RC2 input

    // polarità fronte (scegli: 1 = fronte negativo, 0 = positivo)
    INTCON2bits.INT1EP = 1;  // interrupt su fronte di discesa (tipico pulsante a massa)
    INTCON2bits.INT2EP = 1;

    // priorità (facoltativo): 5
    IPC5bits.INT1IP = 5;     // INT1 priority (IPC5<2:0>)
    IPC7bits.INT2IP = 5;     // INT2 priority (IPC7<6:4>)

    // pulisci flag e abilita
    IFS1bits.INT1IF = 0;
    IFS1bits.INT2IF = 0;
    IEC1bits.INT1IE = 1;     // abilita INT1
    IEC1bits.INT2IE = 1;     // abilita INT2
}

void InitUART3(void)
{//
    U3MODEbits.UARTEN = 0;      // disabilita per configurazione
    U3MODEbits.BRGH   = 1;      // High speed (4x)
    U3BRG = 68;                 // ~115200 bps con FCY=32MHz

    U3STAbits.UTXEN   = 1;      // abilita TX
    U3STAbits.URXISEL = 0;      // interrupt su ogni char (1+ in FIFO)

    IFS5bits.U3RXIF = 0;        // clear flag
    IEC5bits.U3RXIE = 1;        // abilita interrupt RX
    // (opzionale) priorità, se disponibile:
    // IPC20bits.U3RXIP = 5;

    U3MODEbits.UARTEN = 1;      // abilita UART
}



void InitUART4(void) {
  U4MODEbits.UARTEN = 0;                 // disabilita per configurare
    U4MODEbits.BRGH   = 0;                 // low speed
    U4BRG = 207;//(FCY / (16UL * 9600)) - 1;     // 207 a 32MHz

    U4STAbits.URXISEL = 0;   // IRQ su ogni char ricevuto
    U4STAbits.UTXEN   = 1;   // abilita TX (necessario se trasmetti)

    IFS5bits.U4RXIF = 0;     // clear flag
    //IPC22bits.U4RXIP = 5;    // priorità IRQ RX (se questo dà errore, dimmelo)
    IEC5bits.U4RXIE = 1;     // abilita interrupt RX

    U4MODEbits.UARTEN = 1;   // abilita UART (abilita anche la RX)
}

// === Funzione principale ===
int main(void) {
int i = 0;

    ConfigurePLL();
    ConfigureUART3Pins();
    InitUART3();
   
    ConfigureUART4Pins();   
    InitUART4();
   
    ConfigureExternalINTs();
     
    TRISB=0;
    TRISD=0;
    TRISDbits.TRISD15 = 0; // LED1
    TRISDbits.TRISD14 = 0; // LED2
    TRISBbits.TRISB15 = 0; // LED3
    TRISBbits.TRISB14 = 0; // LED4
    TRISBbits.TRISB13 = 0; // LED5
    TRISBbits.TRISB12 = 0; // LED6
   
    TRISGbits.TRISG7 = 0; // enab
   

    LATDbits.LATD15 = 1;
    LATDbits.LATD14 = 1;
    LATBbits.LATB15 = 1;
    LATBbits.LATB14 = 1;
    LATBbits.LATB13 = 1;
    LATBbits.LATB12 = 1;
    LATGbits.LATG7 = 1;
   
    ENAB=0;
   
// Sequenza di lampeggio iniziale per indicare l'avvio
//    for (int i = 0; i < 3; i++) {
    for (i = 0; i < 3; i++) {
        LED1_TOGGLE();
        __delay_ms(100); // Dovrebbe essere 100ms se FCY è 32MHz
        LED1_TOGGLE();
        __delay_ms(100);
    }
   
    // === Configura Timer1 ===
    T1CON = 0;                // Reset T1
    T1CONbits.TCKPS = 0b11;   // Prescaler 1:256
    PR1 = 625;//1250;               // (32MHz / 256) / 1250 = 10ms
    TMR1 = 0;

    IFS0bits.T1IF = 0;        // Pulisci il flag
    IEC0bits.T1IE = 1;        // Abilita interrupt Timer1
    T1CONbits.TON = 1;        // Avvia il timer

    __builtin_enable_interrupts(); // Abilita interrupt globali
   
    // Loop principale: lampeggia
    while (1) {
        LED6_TOGGLE();
        __delay_ms(400); // Dovrebbe essere 100ms se FCY è 32MHz
     
    }
   
}


gld file of bootloader:
Code:
MEMORY
{
  data  (a!xr)   : ORIGIN = 0x800,         LENGTH = 0x4000
  reset          : ORIGIN = 0x0,           LENGTH = 0x4
  ivt            : ORIGIN = 0x4,           LENGTH = 0xFC
  _reserved      : ORIGIN = 0x100,         LENGTH = 0x4
  aivt           : ORIGIN = 0x104,         LENGTH = 0xFC
  app_ivt        : ORIGIN = 0x1A00,        LENGTH = 0x110

#ifdef __BOOTLOADER
  program (xr)   : ORIGIN = 0x400,         LENGTH = 0x1600
#else
  program (xr)   : ORIGIN = 0x1B10,         LENGTH = 0x290E6
#endif

  CONFIG3        : ORIGIN = 0x2ABFA,       LENGTH = 0x2
  CONFIG2        : ORIGIN = 0x2ABFC,       LENGTH = 0x2
  CONFIG1        : ORIGIN = 0x2ABFE,       LENGTH = 0x2
}

#ifdef __APP_IVT_BASE_ADDR
__APP_IVT_BASE = __APP_IVT_BASE_ADDR;
#else
__APP_IVT_BASE = 0x1A00;
#endif

__CONFIG3 = 0x2ABFA;
__CONFIG2 = 0x2ABFC;
__CONFIG1 = 0x2ABFE;

__IVT_BASE  = 0x4;
__AIVT_BASE = 0x104;
__DATA_BASE = 0x800;
__DATA_LENGTH = 0x4000;
__CODE_BASE = 0x400;
__CODE_LENGTH = 0x2A9F8;


When the program compiled with CCS is loaded without the bootloader, it works fine.

Believe me, I’ve done dozens of tests and searched for information online. At this point, it seems there may be some incompatibility between the CCS compiler and the bootloader. I’m currently using CCS version 5.120, and the microcontroller is the 24FJ256GB110.

Please suggest any further tests I could try.
asmallri



Joined: 12 Aug 2004
Posts: 1651
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Aug 13, 2025 11:04 pm     Reply with quote

I have not used the Microchip bootloader you are using however I do have a lot of experience working with bootloaders.

My suggestion is don't assume that bootloaders are interchangeable. For example, some bootloaders remap interrupt vectors and others reserve this interrupt vector space for the applications use.

There are a number of things to be taken into account when using a bootloader. A bootloader will normally not allow the config fuses to be changed by the application. This avoids accidentally bricking the hardware in the field when bootloading an application image contains fuse settings that are incorrect.

What I typically do when porting a bootloader to a new hardware platform is use the application config fuse requirements and put these into the bootlaoder. The first step in the process of is to debug your application without the bootloader being present. The end result of this is the application will now contain the required config fuse settings. If your application required code protect settings to be enabled for production use, you will need to disable this code protection to enable the PIC's program memory to be read back with the debugger / programmer, so you can validate the boatload process. Once you have debugged the bootloader / application combination you can then add the code protection back into the bootloader.

Steps:
1. Debug your application and disable code protection.
2. Program the PIC with your application then immediately reads back the contents of program memory and save it as say app.hex.
3. Modify the bootloader to use the identical fuses required by the application
4. Program the bootloader into your target and immediately read back the contents of the program memory and save it as ldr.hex
5. Load the application program using the bootloader and immediately read back the contents of the program memory and save it as ldr-app.hex
6. Use a File compare program (I use ExamDif Pro) and compare the ldr.hex file and the ldr-app.hex file. The ldr.hex file should be completely embedded in the ldr-app.hex file
7. Repeat the process by comparing the app.hex file with the ldr-app.hex file. The only thing in the app.hex file that should be different is the reset vector, which in the ldr-app.hex file will be the bootloader reset vector and the actual applications vector will moved to a parameter block located elsewhere in program memory. This block will contain the application reset vector as well as potentially status information used by the bootloader. An example of this status is "is there an application image present in program memory.

8. Once the comparisons are correct, the solution should be good to go. Reinstall the code protection in the bootloader if required.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
temtronic



Joined: 01 Jul 2010
Posts: 9566
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Aug 14, 2025 5:42 am     Reply with quote

i don't use that PIC but 'historically' you normally have to read the UART buffer before clearing it's interrupt.
Probably not the problem but simple to test. just change the ISR code,recompile and run.
Ttelmah



Joined: 11 Mar 2010
Posts: 19926

View user's profile Send private message

PostPosted: Thu Aug 14, 2025 9:18 am     Reply with quote

Er.

You #build line relocating the application is inside a section only used when
bootloader is defined.
Result as posted the code will not be relocated to be built for use with a
bootloader.......
So will not work.
Ttelmah



Joined: 11 Mar 2010
Posts: 19926

View user's profile Send private message

PostPosted: Fri Aug 15, 2025 9:24 am     Reply with quote

Two things worry me in what you have posted.
First get rid of DISABLE_INTS in the serial declarations. This is only wanted
when doing software serial to prevent interrupts from interfering with this code.
But then the big one.Your Microchip setup for the IVT, does not agree
with the location you are putting the IVT in the CCS code.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group