|
|
View previous topic :: View next topic |
Author |
Message |
newguy
Joined: 24 Jun 2004 Posts: 1908
|
5.074 HIGH ints & PIC18F25K40 bug [SOLVED] |
Posted: Fri Aug 25, 2017 6:57 pm |
|
|
Just a warning, 5.074 will enable an interrupt designated as high when you enable a low priority interrupt. I found the behaviour with CCP1 (high) being automatically enabled when I enabled timer 2's interrupt. PIC18F25K40.
And to top off this gem of a day, I finally got my CCS order of 2 bare development boards today, 17 days after I ordered them. Canada Post took 12 days to clear the package through customs. Anyway, when I opened it I found that I'm missing one of the boards I paid for.
Never should have got out of bed this morning.
Last edited by newguy on Mon Aug 28, 2017 10:24 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Sat Aug 26, 2017 8:17 am |
|
|
Er. Not that I can see.
Code: |
.................... enable_interrupts(GLOBAL);
01C0: MOVLW C0
01C2: IORWF FF2,F
.................... enable_interrupts(INT_TIMER2);
01C4: MOVLB E
01C6: BSF xC6.1
|
It is only setting bit 1, EC6, which is Timer2 interrupt enable.
This is compiled for your chip with 5.074.
HIGH INTS is enabled, and CCP1 is set as high priority:
Code: |
#include <main25K.h>
#device HIGH_INTS=TRUE
#USE DELAY (CRYSTAL=20Mhz)
#INT_CCP1 HIGH
void int_ccp(void)
{
}
#INT_TIMER2
void int_tick(void)
{
}
void main()
{
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER2);
//etc...
|
|
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Sat Aug 26, 2017 9:30 am |
|
|
On Monday I have to strip down my program to the bare minimum, but some combination of what I'm setting is also setting the CCP1 interrupt to enabled, but only if the HIGH is also set.
When 5.074 was released I was actually relieved because I had to do a lot of juggling to get things to work with 5.073 and the 25K40. I installed it, compiled, programmed my PIC, and.....it hung. ....Screw it, I'm reverting. No time to dig. ...Until yesterday when I was having the really weird hardware issues, so in desperation I compiled a completely stripped down version with 5.074 and tried that, and it hung too. Then I dug in a bit, because why not, I'm already annoyed.
I had stripped down the code to do the initializations (hardware and variables), but then completely stripped out the "running functions" and just put an initial serial transmit of a single character before the while() loop, and in the loop, I put another serial transmit of a different character & delay.
If global interrupts were enabled, the code would hang - initial character would appear, but not the 2nd (certainly not repeating). Comment out the global enable and it ran fine.
Okay, I had two interrupts enabled - RDA and timer 2. Commented out RDA (put the global back in), and...still hung. Put RDA back in and commented out timer 2 - runs fine. Okay, why? High ints - that's the only "weird" interrupt stuff I'm doing, so I commented out the #device high ints line and also the HIGH in the ccp1 interrupt. Runs fine. Weird because I'm not only NOT enabling the ccp1 interrupt, I'm not even powering the ccp1 peripheral. Really. This is a low power project and I'm setting its PMD bit to 1 initially. In this stripped down version it's not powered at all.
As I said, Monday I'll strip it back to bare minimum and post something that demonstrates the problem. 5.073 runs fine but 5.074 hangs if the high ints option is used. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Mon Aug 28, 2017 7:40 am |
|
|
This demonstrates the problem. Compile with 5.073 and it runs (initial transmission of 'r' followed by reads of port B every 250ms), and if you compile with 5.074, it hangs. All that emerges is the initial 'r'. Comment out the high ints declaration (and the HIGH in the CCP1 interrupt), and it runs with 5.074.
Code: | #include <18F25K40.h>
#device ADC=10
#device HIGH_INTS=TRUE
#FUSES HS //High speed Osc (> 4MHz for PCM/PCH)
#FUSES RSTOSC_EXT_PLL //On Power-up clock running from External with PLL
#FUSES NOCLKOUT //I/O function on OSC2
#FUSES CKS //Clock Switching Enabled
#FUSES MCLR //Master Clear pin enabled
#FUSES PUT //Power Up Timer
#FUSES NOLPBOR //Low-Power Brownout reset is disabled
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV28 //Brownout reset at 2.8V
#FUSES ZCDDIS //Zero-cross detect circuit is disabled at POR
#FUSES NOPPS1WAY //Allows reconfiguration of peripheral pins
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDTSW //Watch Dog Timer Postscale settable in software
#FUSES WDTWIN_SW //Watchdog Window is settable in software
#FUSES WDTCLK_SW //WDT clock source settable in software
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTC //Configuration registers not write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOSCANE //Scanner module is not available for use
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPD //No EE protection
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#use delay(clock=64000000,crystal=16000000)
#opt compress
#case
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
// v5.073 compiler bug workaround inclusions begin
#byte T6CON=getenv("SFR:T6CON") // timer 6 control register - necessary because compiler wasn't disabling timer 6
#byte T4CON=getenv("SFR:T4CON") // timer 4 control register - necessary because compiler wasn't disabling timer 4
#byte RC2PPS=getenv("SFR:RC2PPS") // PIN_C2 output peripheral pin select register - CCP2 output
#byte RC5PPS=getenv("SFR:RC5PPS") // PIN_C5 output peripheral pin select register - MSSP data output
#byte RC6PPS=getenv("SFR:RC6PPS") // PIN_C6 output peripheral pin select register - UART TX output
#byte RB5PPS=getenv("SFR:RB5PPS") // PIN_B5 output peripheral pin select register - either manual or CCP1
#byte CCP1PPS=getenv("SFR:CCP1PPS") // CCP1 input pin select register
#byte RA0PPS=getenv("SFR:RA0PPS")
#byte RX1PPS=getenv("SFR:RXPPS") // UART RX pin select register (note name discrepancy because apparently neither CCS nor MC follow the names specified in the data sheet)
#define MSSP_DATA_MANUAL_CONTROL 0
#define MSSP_DATA_MSSP_CONTROL 14
#define SIGNAL_SENSORS_MANUAL_CONTROL 0
#define SIGNAL_SENSORS_CCP2_CONTROL 6
#define CCP1_TO_PIN_B5 13
#define UART_TRANSMIT 9
#define UART_RECEIVE_TO_PIN_C7 23
#byte BAUD1CON=getenv("SFR:BAUD1CON") // UART baud rate divisor register
#byte TX1STA=getenv("SFR:TX1STA") // UART TX status register
#byte RC1STA=getenv("SFR:RC1STA") // UART RX status register
#byte SP1BRGL=getenv("SFR:SP1BRGL") // UART low baud rate register
#define TX1STA_value 0xa2
#define RC1STA_value 0x90
#define SP1BRGL_value 103
// 16 MHz clock / (16 * (103 + 1)) = 9615.4 BAUD, 0.16% high - well within spec
#byte TX1REG=getenv("SFR:TX1REG")
#byte RC1REG=getenv("SFR:RC1REG")
#byte CPUDOZE=getenv("SFR:CPUDOZE")
// v5.073 compiler but workaround inclusions end
#byte PRODH=getenv("SFR:PRODH")
#byte PMD0=getenv("SFR:PMD0")
#byte PMD1=getenv("SFR:PMD1")
#bit TMR6MD=PMD1.6
#bit TMR5MD=PMD1.5
#bit TMR4MD=PMD1.4
#bit TMR3MD=PMD1.3
#bit TMR2MD=PMD1.2
#bit TMR1MD=PMD1.1
#bit TMR0MD=PMD1.0
#byte PMD2=getenv("SFR:PMD2")
#bit ADCMD=PMD2.5
#byte PMD3=getenv("SFR:PMD3")
#bit CCP2MD=PMD3.1
#bit CCP1MD=PMD3.0
#byte PMD4=getenv("SFR:PMD4")
#bit UART1MD=PMD4.6
#byte PMD5=getenv("SFR:PMD5")
#byte CCPTMRS=getenv("SFR:CCPTMRS")
#byte CCP1CON=getenv("SFR:CCP1CON")
#bit CCP1ENABLE=CCP1CON.7
#byte CCP2CON=getenv("SFR:CCP2CON")
#bit CCP2ENABLE=CCP2CON.7
#byte T5GCON=getenv("SFR:T5GCON")
#byte T5CLK=getenv("SFR:T5CLK")
#byte T5CON=getenv("SFR:T5CON")
#byte T6PR=getenv("SFR:T6PR")
#byte T6CLK=getenv("SFR:T6CLK")
#byte TMR0H=getenv("SFR:TMR0H")
#byte TMR0L=getenv("SFR:TMR0L")
#byte SSP1BUF=getenv("SFR:SSP1BUF")
#byte ANSELA=getenv("SFR:ANSELA")
#byte ANSELB=getenv("SFR:ANSELB")
#byte ANSELC=getenv("SFR:ANSELC")
#byte T1GPPS=getenv("SFR:T1GPPS")
#byte PPSLOCK=getenv("SFR:PPSLOCK")
#define TX_BUFFER_SIZE 256
#define RX_BUFFER_SIZE 128
struct {
int1 tx_in_progress_flag;
int1 message_rxd_flag;
unsigned int8 num_rxd_messages;
unsigned int8 tx_buffer[TX_BUFFER_SIZE];
unsigned int8 rx_buffer[RX_BUFFER_SIZE];
} comm;
unsigned int8 *comm_tx_rd_pointer;
unsigned int8 *comm_tx_wr_pointer;
unsigned int8 *comm_rx_rd_pointer;
unsigned int8 *comm_rx_wr_pointer;
struct {
int1 fired_flag;
} tenms_timer;
void bputc(unsigned int8 c) {
*comm_tx_wr_pointer = c;
if (++comm_tx_wr_pointer == (&comm.tx_buffer[0] + TX_BUFFER_SIZE)) {
comm_tx_wr_pointer = &comm.tx_buffer[0];
}
if (comm.tx_in_progress_flag == FALSE) {
comm.tx_in_progress_flag = TRUE;
enable_interrupts(INT_TBE); // enable the transmit buffer empty interrupt
}
}
#int_CCP1 HIGH
void ccp1_isr(void) {
}
#int_TIMER2
void timer2_isr(void) {
tenms_timer.fired_flag = TRUE;
}
#int_RDA
void rda_isr(void) {
unsigned int8 c;
c = RC1REG;
*comm_rx_wr_pointer = c;
if (++comm_rx_wr_pointer == (&comm.rx_buffer[0] + RX_BUFFER_SIZE)) {
comm_rx_wr_pointer = &comm.rx_buffer[0];
}
if (c == 0x0d) {
comm.num_rxd_messages++;
comm.message_rxd_flag = TRUE;
}
}
#int_TBE
void tbe_isr(void) {
if (comm_tx_rd_pointer != comm_tx_wr_pointer) { // ...if there's more in the buffer to transmit...
TX1REG = *comm_tx_rd_pointer;
if (++comm_tx_rd_pointer == (&comm.tx_buffer[0] + TX_BUFFER_SIZE)) {
comm_tx_rd_pointer = &comm.tx_buffer[0];
}
if (comm_tx_rd_pointer == comm_tx_wr_pointer) {
comm.tx_in_progress_flag = FALSE;
disable_interrupts(INT_TBE);
}
}
else { // no more characters in the buffer - disable the interrupt
comm.tx_in_progress_flag = FALSE;
disable_interrupts(INT_TBE);
}
}
void main(void) {
// kill all peripherals...
PMD0 = 0x7b; // ...except the peripheral clock distribution network and EEPROM
PMD1 = 0xff;
PMD2 = 0xff;
PMD3 = 0xff;
PMD4 = 0xbf; // ...except the UART
PMD5 = 0xff;
bit_clear(BAUD1CON, 3); // 8 bit baud rate generator, not 16
SP1BRGL = SP1BRGL_value;
TX1STA = TX1STA_value;
RC1STA = RC1STA_value;
RC6PPS = UART_TRANSMIT;
RX1PPS = UART_RECEIVE_TO_PIN_C7;
ANSELC = 0x00; // all digital
output_c(0x41); // set outputs first
set_tris_c(0x80); // set proper directions on the port
ANSELB = 0x00; // all digital
output_b(0x00); // set outputs first
set_tris_b(0x20); // finally set proper directions on the port
comm.tx_in_progress_flag = FALSE;
comm.message_rxd_flag = FALSE;
comm.num_rxd_messages = 0;
comm_tx_rd_pointer = &comm.tx_buffer[0];
comm_tx_wr_pointer = &comm.tx_buffer[0];
comm_rx_rd_pointer = &comm.rx_buffer[0];
comm_rx_wr_pointer = &comm.rx_buffer[0];
tenms_timer.fired_flag = FALSE;
TMR2MD = 0;
delay_cycles(3);
setup_timer_2(T2_CLK_INTERNAL | T2_DIV_BY_128, 249, 5); // start timer 2 with a 10ms overflow/interrupt
enable_interrupts(INT_TIMER2);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
TX1REG = 'r';
while (TRUE) {
printf(bputc, "%x\n\r", input_b());
delay_ms(125);
output_toggle(PIN_C2);
delay_ms(125);
}
} |
|
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Mon Aug 28, 2017 10:25 am |
|
|
CCS just sent me an updated DLL which fixed the issue. I imagine that the fix will be rolled into 5.075, whenever that's released. |
|
|
|
|
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
|