|
|
View previous topic :: View next topic |
Author |
Message |
edweir
Joined: 07 Jan 2010 Posts: 4
|
RDA Int causes chip crash/reset |
Posted: Thu Jan 07, 2010 4:37 pm |
|
|
Hi all,
As the title states, when I enter my RDA interrupt which is triggered by responses from a zigbee chip via the RS232 protocol, the chip resets.
Using:
Compiler -- v4
PIC -- 16f886
The purpose of this RDA interrupt is to read in the characters being sent to the MCU, do a quick determination if the message that's coming in is a broadcast (BCAST), and then if it is, determine what type.
Code below:
Code: |
// delay after any Zigbee command
#define ZigbeeDelay 70
// include statement for PIC specific library/fuses and clock
//library
#include "16F886.h"
#fuses HS,WDT,NOPROTECT,NOLVP,INTRC_IO,NOBROWNOUT
#use delay(clock=8000000, restart_wdt)
#use rs232(baud=19200, ERRORS, xmit=PIN_C6, rcv=PIN_C7)
#define ADC_SCK PIN_A0
#define MUX_EN PIN_A3
#define MUX_A0 PIN_A4
#define MUX_A1 PIN_A5
#define MUX_A3 PIN_A6
#define MUX_A2 PIN_A7
#define ADC_DIN PIN_B1
#define LED2 PIN_B2
#define ADC_CONV PIN_B5
#define TempPower PIN_B4
#define LED1 PIN_C1
#define EEPROM_SCL PIN_C3
#define EEPROM_SDA PIN_C4
// input character for all serial reads
byte keybdbyte;
char bcast_char_array[] = {'B','C','A','S','T'};
char shift_char_array[5];
char bcast[5]; //switched from 16 to test ram
byte bcast_flag = 1;
char START_array[] = {'S','T','A','R','T'};
char END_array[] = {'E','N','D'};
char DATA_array[] = {'D','A','T','A'};
byte end_flag = 0;
// Subroutine declarations
extern void set_mux_chan(int m_chan);
extern char IsCommand(char *bc, char *ta, int len);
extern void interpret_comm();
extern void get_adc_data(int buff);
extern void clear_eeprom();
extern void EEPROMR();
extern int16 measure(int channel, int average);
extern char ZigbeeJPAN();
extern void ZigbeeInit();
extern void TempRead();
extern void ZigbeeSend();
/////////////////////////////////////////
//////////////////
// main program //
//////////////////
void main() {
int k;
setup_timer_2(T2_DIV_BY_16, 250, 8);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
// Ports
set_tris_a(0b00000110);
set_tris_b(0b00000011);
set_tris_c(0b01001000);
printf("boot 1/7/2010\n\r");
// indicate power-up complete
for(k=0;k<=2;k++) {
output_high(LED2);
output_high(LED1);
delay_ms(250);
output_low(LED2);
output_low(LED1);
delay_ms(250);
}
while(1){
delay_ms(1000);
}
}
////////////////////////
// INTERRUPT HANDLERS //
////////////////////////
#INT_RDA
void RDA_isr() {
int n;
/*
//DIAGNOSTIC LED BLIP
int ledtick;
for(ledtick=0;ledtick<=2;ledtick++) {
output_high(LED2);
delay_ms(250);
output_low(LED2);
output_high(LED1);
delay_ms(250);
output_low(LED1);
}
*/
// get character
keybdbyte = getc();
for(n = 0; n < (sizeof(shift_char_array)-1); n++) {
shift_char_array[n] = shift_char_array[n+1];
}
shift_char_array[0] = keybdbyte;
// test for BCAST
if (1 == (bcast_flag = IsCommand(bcast_char_array,
shift_char_array, sizeof(bcast_char_array)))) {
// get the broadcast after the equals sign
while(keybdbyte != '=') {
keybdbyte = getc();
//### add break
}
if (keybdbyte == '=') {
while((keybdbyte = getc()) != '!') {
bcast[n] = keybdbyte;
}
}
}
} // end RDA interrupt
//////////////////
// //
// Subroutines //
// //
//////////////////
// checks if the array is a passed command
char IsCommand(char *bc, char *ta, int len) {
short int a;
char flag = 1;
// test broadcast to see if it is the command
for(a = 0; a < len; a++) {
if (bc[a] != ta[a])
flag = 0;
}
return flag;
}
// 3 commands implemented 11/20/2009: START, END, DATA
void interpret_comm() {
if (IsCommand(bcast, START_array, sizeof(START_array))) {
// start the data reading
printf("start bcast received\n\r");
// TempRead();
// TempDataCount = TempDataCount +1;
}
else if (IsCommand(bcast, END_array, sizeof(END_array))) {
// set end flag to stop readings
end_flag = 1;
printf("end bcast received\n\r");
}
else if (IsCommand(bcast, DATA_array, sizeof(DATA_array))) {
// send data
printf("data bcast received\n\r");
// ZigbeeSend();
delay_ms(10000);
}
}
|
I've taken out a lot of the guts of the code to get something relatively short and compilable... With the full code, however, I know based on some LED indicators (shown commented out) that I'm getting into the RDA interrupt handler... but once there I don't know where the problem is.
Thanks for the help! _________________ Cor. 's a rough world 'innit? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 07, 2010 4:50 pm |
|
|
Post the full version. Each version has different bugs affecting different PICs.
Quote: | #fuses HS,WDT,NOPROTECT,NOLVP,INTRC_IO,NOBROWNOUT |
You have two oscillator fuses. You should only have one.
Quote: | #INT_RDA
void RDA_isr() {
int n;
// get character
keybdbyte = getc();
if (keybdbyte == '=') {
while((keybdbyte = getc()) != '!') {
bcast[n] = keybdbyte;
|
You are waiting for multiple bytes inside the #int_rda routine.
That's not the preferred way to do it. You should only get
one per pass, in the interrupt routine. Suppose all the
expected bytes don't come in. You are then locked up in
the interrupt service routine.
I suspect this is why you have the Watchdog timer enabled,
as a 'fix' for this problem. Because you don't have restart_wdt
as a parameter in your #use rs232 statement, the getc() routine
will not restart the WDT periodically. The getc() function
sits in a loop, waiting for a char. Eventually you will get a WDT reset.
The solution is to use a buffer, similar to the Ex_sisr.c example.
There are also examples in the forum archives for receiving
and decoding command strings (such as NMEA-0183 for GPS)
which show how to use #int_rda for this purpose. (Getting one
char per pass).
Quote: | while((keybdbyte = getc()) != '!') {
bcast[n] = keybdbyte; |
This code looks unsafe. What if the incoming string doesn't match
your expected format. The code could write past the end of the
array and overwrite other RAM locations, causing erratic program
behavior or a crash. |
|
|
edweir
Joined: 07 Jan 2010 Posts: 4
|
|
Posted: Thu Jan 07, 2010 5:01 pm |
|
|
Thanks for the quick replies! I'll take a look at these and get back to you as soon as I can. _________________ Cor. 's a rough world 'innit? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 07, 2010 5:17 pm |
|
|
MPLAB only includes the PCB compiler (to my knowledge), which is
for low-end PICs.
It doesn't include the PCM compiler, which is used for mid-range PICs
such as the 16F886.
The version number is given at the top of the .LST file, which will be in
your project directory after a successful compilation. It's a 4 digit number
in this format: 4.xxx |
|
|
edweir
Joined: 07 Jan 2010 Posts: 4
|
|
Posted: Thu Jan 07, 2010 5:21 pm |
|
|
Thank you. The compiler is version 4.057. _________________ Cor. 's a rough world 'innit? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 07, 2010 5:34 pm |
|
|
I don't recall that vs. 4.057 had any particular faults with respect to
causing a program to reset.
Instead of using your code, look at Ttelmah's method for detecting
commands from the serial port:
http://www.ccsinfo.com/forum/viewtopic.php?t=31144 |
|
|
|
|
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
|