 |
 |
View previous topic :: View next topic |
Author |
Message |
ciccioc74
Joined: 23 Mar 2010 Posts: 44
|
|
Posted: Thu Feb 13, 2025 3:41 am |
|
|
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
|
|
Posted: Thu Feb 13, 2025 6:39 am |
|
|
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
|
|
Posted: Thu Mar 13, 2025 11:53 am |
|
|
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
|
|
Posted: Fri Mar 14, 2025 2:24 am |
|
|
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
|
|
Posted: Fri Mar 14, 2025 2:43 am |
|
|
Ok. Thank. |
|
 |
ciccioc74
Joined: 23 Mar 2010 Posts: 44
|
|
Posted: Wed Aug 13, 2025 7:46 am |
|
|
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
|
|
Posted: Wed Aug 13, 2025 11:04 pm |
|
|
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
|
|
Posted: Thu Aug 14, 2025 5:42 am |
|
|
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
|
|
Posted: Thu Aug 14, 2025 9:18 am |
|
|
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
|
|
Posted: Fri Aug 15, 2025 9:24 am |
|
|
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. |
|
 |
|
|
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
|