View previous topic :: View next topic |
Author |
Message |
ciccioc74
Joined: 23 Mar 2010 Posts: 39
|
Issue PIC24FJ256GB110 irq Serial1 (#INT_RDA) Freez system |
Posted: Mon Feb 10, 2025 10:00 am |
|
|
Hello everyone,
I am programming the PIC24FJ256GB110 and loading the firmware using the bootloader provided by Microchip. Below is my configuration:
Code: | #ZERO_RAM
#include <24FJ256GB110.h>
#device ADC=10
#device ICSP=2
// Configuration for exp16_pic24fj256gb110_pim.x.production.hex
#define LOADER_END 0x17FF
#define APP_IVT 0x1804
#build(reset=LOADER_END+1, interrupt=APP_IVT)
#org 0, LOADER_END{} // Ensures the bootloader memory space is not overwritten
#fuses NONE
#use delay(clock=32000000)
#pin_select U1TX=PIN_G6
#pin_select U1RX=PIN_G8
#use rs232(UART1, baud=9600, errors, stream=RS485, ERRORS, DISABLE_INTS)
#pin_select U2TX=PIN_D10
#pin_select U2RX=PIN_D11
#use rs232(UART2, baud=115200, errors, stream=ESP, ERRORS, DISABLE_INTS)
#pin_select INT1 = PIN_C3
#pin_select INT2 = PIN_C2
#define LED3 PIN_C13
#define LED4 PIN_C14
int cont_1s = 0;
int temp;
#INT_TIMER2
void my_timer2_isr() {
if (++cont_1s > 100) { // 0.5 seconds
cont_1s = 0;
output_toggle(PIN_D15);
}
}
#INT_RDA2
void myRXisr() {
do {
temp = fgetc(ESP);
output_toggle(LED3);
} while (kbhit(ESP));
}
#INT_RDA
void myRXisr485() {
do {
temp = fgetc(RS485);
output_toggle(LED4);
} while (kbhit(RS485));
}
void main() {
delay_ms(1000);
output_c(0);
set_tris_c(0b0000000000001110);
output_d(0);
set_tris_d(0b0000100001001100);
setup_timer2(TMR_INTERNAL | TMR_DIV_BY_64, 1249);
enable_interrupts(INT_TIMER2);
enable_interrupts(INT_RDA2);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while (1) {
delay_ms(1000);
output_toggle(PIN_D14);
}
}
|
Bootloader Memory Configuration (.gld file)
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 = 0x1800, LENGTH = 0x110
#ifdef __BOOTLOADER
program (xr) : ORIGIN = 0x400, LENGTH = 0x1400
#else
program (xr) : ORIGIN = 0x1910, LENGTH = 0x292E6
#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 = 0x1800;
#endif
|
If i load the firmware without bootloader the program works fine
Issue Description
The Timer2 interrupt (#INT_TIMER2) and the UART2 receive interrupt (#INT_RDA2) work as expected. However, when data arrives on UART1 (#INT_RDA), the system completely freezes.
Questions
Could this be related to interrupt priority issues?
Is there something in my configuration that could cause #INT_RDA to block execution?
Any suggestions on debugging this issue?
Thank you in advance for your help! |
|
 |
temtronic
Joined: 01 Jul 2010 Posts: 9425 Location: Greensville,Ontario
|
|
Posted: Mon Feb 10, 2025 12:12 pm |
|
|
hmm,... UART1 says 'rs485'..... so how do you control xmt/rcv ? RS485 usually needs a 'control ' pin in the #use RS232(...options....)
probably not it but looked 'odd' to me....
Also might be a good idea to use a 'timed' receive.Real handy when the cable comes out of the connector........or 'sender' doesn't finsh. |
|
 |
ciccioc74
Joined: 23 Mar 2010 Posts: 39
|
|
Posted: Mon Feb 10, 2025 5:01 pm |
|
|
Thank you very much for your answer.
As you say the UART2 is connected to a 485. The enable pin is connected to the PIN_G7 pin. I think you refer to this when you say "xmt/rcv". I added the line Code: | set_tris_g (0b0000000100000000);
output_low(PIN_G7); | but it doesn’t change anything. Actually I had already done this test and also change the irq priorities, disable and re-enable uart1 Code: | setup_uart(FALSE);
delay_ms(100);
setup_uart(9600,RS485);
setup_uart(TRUE); | use but I’m not sure I did everything correctly.
Remember that without bootloader everything works for this I think the problem is the interrupt address. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19730
|
|
Posted: Tue Feb 11, 2025 2:43 am |
|
|
RS485, is normally a half duplex signal. Just two wires used, and you can
only transmit _or_ receive at any time. This normally has a direction control
line to set whether the buffer is transmitting or receiving, and you have
to set the direction control to transmit (xmt) , before sending a byte, and
back to receive (rcv), when waiting to receive/ Also the hardware of the
buffer chip needs to have the receive line from this back to the processor
with a pulll up resistor, so when transmitting this line (which will be floating),
is pulled up so the processor does not see spurious data. The enable line
is normally separate, and enables the transmit buffer. If your enable line
is connected to the receive enable as well, and this is off, and the receive
line is floating, then the PIC may be receiving garbage. |
|
 |
ciccioc74
Joined: 23 Mar 2010 Posts: 39
|
|
Posted: Tue Feb 11, 2025 3:12 am |
|
|
Thanks again for the time you take with me.
I tried to reverse the ports. now 485 works ( generates the interrupt) but as soon as a byte arrives on uart1 (#INT_RDA) it freezes.
Code: | #INT_RDA
void myRXisr(){
do{
temp= fgetc(ESP);
output_toggle(LED3);
} while (kbhit(ESP));
}
#INT_RDA2
void myRXisr485(){
do{
temp= fgetc(RS485);
output_toggle(LED4);
} while (kbhit(RS485));
} |
For testing I also inserted 2 other interrupts and they work Code: | #INT_EXT1
void ext1IRQ(){
output_toggle(PIN_D14);
}
#INT_EXT2
void ext2IRQ(){
output_toggle(PIN_B15);
} |
|
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19730
|
|
Posted: Tue Feb 11, 2025 5:35 am |
|
|
First thing, remove DISABLE_INTS from your serial declarations.
This is only wanted when you are doing software serial really, and
certainly should not be there on serials handled by interrupts. May
well cause an issue. Also having errors twice should be corrected.
The suspicion would be that your compiler is not reading the UART
data register correctly for this port. What is your compiler version?????
That was an issue on some of the early compilers. |
|
 |
ciccioc74
Joined: 23 Mar 2010 Posts: 39
|
|
Posted: Tue Feb 11, 2025 9:16 am |
|
|
Thank you. I use Version: 5.071. I removed DISABLE_INT and changed the serial ports ( now use 3 and 4 after several tests) and I have a strange behavior also with EXT1 and EXT2. For the first 9 seconds (before enabling INT_RDA4), the #INT_TIMER2 #INT_RDA3 #INT_EXT1 #INT_EXT2 will work. Just (at the tenth second) enabled INT_RDA4 some interrupts are blocked Code: | #ZERO_RAM
#include <24FJ256GB110.h>
#device ADC=10
#device ICSP=2
//conf da usare con exp16_pic24fj256gb110_pim.x.production.hex
#define LOADER_END 0x17FF
#define APP_IVT 0x1804
#build(reset=LOADER_END+1, interrupt=APP_IVT)
#org 0, (LOADER_END ){} // nothing will replace the bootloader memory space
#fuses NONE
#use delay(clock=32000000)
#pin_select U4TX=PIN_G6
#pin_select U4RX=PIN_G8
#use rs232(UART4, baud=9600, errors, stream=RS485,ERRORS)
#pin_select U3TX=PIN_D10
#pin_select U3RX=PIN_D11
#use rs232(UART3, baud=115200, errors, stream=ESP,ERRORS)
#byte INTCON2 = 0x82
#bit ALTIVT = INTCON2.15
#byte INTCON1 = 0x80
#bit NSTDIS = INTCON1.15
#byte U1STA = 0x222
#bit OERR = U1STA.1
#pin_select INT1 = PIN_C3
#pin_select INT2 = PIN_C2
#define LED3 PIN_C13
#define LED4 PIN_C14
int cont_1s=0;
volatile int temp;
#INT_TIMER2
void my_timer2_isr (){
if(++cont_1s>100){//0,5 seconds
cont_1s=0;
output_toggle(PIN_D15);
}
}
#INT_RDA3
void myRXisr(){
do{
temp= fgetc(ESP);
output_toggle(LED3);
} while (kbhit(ESP));
}
#INT_RDA4
void myRXisr485(){
do{
temp= fgetc(RS485);
output_toggle(LED4);
} while (kbhit(RS485));
}
#INT_EXT1
void ext1IRQ(){
output_toggle(PIN_D14);
}
#INT_EXT2
void ext2IRQ(){
output_toggle(PIN_B15);
}
void main() {
int cont=0;
delay_ms(1000);
set_tris_b (0b0000001100101100);
output_c(0);
set_tris_c (0b0000000000001110);
output_d(0);
set_tris_d (0b0000100001001100);
set_tris_g (0b0000000100000000);
setup_timer2(TMR_INTERNAL | TMR_DIV_BY_64, 1249);
setup_uart(FALSE);
delay_ms(100);
setup_uart(9600,RS485);
setup_uart(TRUE);
NSTDIS=0;
enable_interrupts(INT_EXT1);
enable_interrupts(INT_EXT2);
enable_interrupts(INT_TIMER2);
enable_interrupts(INT_RDA3);
//ALTIVT =1;
enable_interrupts(GLOBAL);
output_low(PIN_G7);
while(1){
delay_ms(1000);
if( cont++>10)
enable_interrupts(INT_RDA4);
}
}
| [/code] |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19730
|
|
Posted: Tue Feb 11, 2025 11:35 am |
|
|
Where is the clock coming from?.
You are not specifying a clock source.
5.071 is terrifyingly old. Will have to go and research the problems this version
had with this chip.
That it is going wrong after time, suggests you may have hardware problems. |
|
 |
ciccioc74
Joined: 23 Mar 2010 Posts: 39
|
|
Posted: Wed Feb 12, 2025 2:19 am |
|
|
Hello. Thanks for the answer. I installed demo version 5.119 and the problem remains. This is the config bit of the bootloader Code: | /** 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 = OFF // Internal USB 3.3V Regulator Disable bit (Regulator is disabled)
#pragma config IOL1WAY = 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) |
|
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19730
|
|
Posted: Wed Feb 12, 2025 2:47 am |
|
|
Glaring problem here:
IOL1WAY = ON
This means that your main code cannot do any PPS setups. So the pin
mapping will not be happening.
You must never have this set when using a bootloader.
Have just checked and your compiler does access the correct register
bits for the UART.
Another glaring one:
DISUVREG = OFF
This is turning _on_ the USB Vreg. This must be ON. .
The bit is a bit to disable the regulator. So works backwards. This bit
must be on, or the internal charge pump will be trying to run. |
|
 |
ciccioc74
Joined: 23 Mar 2010 Posts: 39
|
|
Posted: Wed Feb 12, 2025 4:25 am |
|
|
Thank you for all the suggestions you are giving me.
I changed the IOL1WAY and DISUVREG bit in the config bit but I still have some problems ( now, as soon as you enable irq from serial3, it stops on timer 2).
I also checked the config bits one by one on pickit 0.001.x.011.10.0.0.0.1.10
i use a demo version of 5.119 |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19730
|
|
Posted: Wed Feb 12, 2025 4:47 am |
|
|
Though it shouldn't cause a problem, for an 8MHz crystal, XT is the
recommended oscillator. HS will overdrive it a little. Table 8-3. Valid
oscillator configurations.
So are you saying that now if you enable UART3, it disables the timer?. |
|
 |
ciccioc74
Joined: 23 Mar 2010 Posts: 39
|
|
Posted: Wed Feb 12, 2025 5:14 am |
|
|
thank you. Quote: | for an 8MHz crystal, XT is the
recommended oscillator | How many things to check... done. Yes the problem is that when I enable the irq on uart3 of the serial it blocks the timer 2 (and does not work either the UART3) |
|
 |
ciccioc74
Joined: 23 Mar 2010 Posts: 39
|
|
Posted: Thu Feb 13, 2025 2:32 am |
|
|
Quote: | Have just checked and your compiler does access the correct register
bits for the UART. |
so you think that if I set all the serial registers manually I could solve it? Also for the 5.119 version? |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19730
|
|
Posted: Thu Feb 13, 2025 3:18 am |
|
|
No, the registers are correct for UART3 as well.
The most likely cause is that you have got something confused in your
swapping of ports used. So the INT_RDA3, is not actually reading the
stream corresponding to UART3. You need to go and check very carefully.
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. |
|
 |
|