|
|
View previous topic :: View next topic |
Author |
Message |
wiseacre
Joined: 14 Jun 2012 Posts: 9
|
Firmware won't start after power off/on |
Posted: Thu Jun 14, 2012 11:40 am |
|
|
I've got a really strange problem I've been unable to figure out, along with some help from a coworker. I've written a program (that still isn't fully complete, but working) that works just fine when I program the PIC. However, if I unplug power and then power the board back up, the program won't run. I've done this both with and without the debugger attached. If I try to reprogram the PIC after doing this, the code won't work. If I program another program onto the PIC, that program will work and then I can program my program and have it work. This second program that works will also start on power up just fine, which leads me to believe it's something in the code, but we've been working on this for days and have yet to figure it out. I don't have the code fully commented yet, but this is what I'm working with:
Code: |
/*=================================================================
Name : StatusIndicatorLIghtsDisplay.c
Author : Valerie Halbur
Copyright : 2012 Mayo Foundation for Medical Education and Research
Description : Status Indicator Lights Display Control Software
==================================================================
*/
#define DEV_BOARD
#include <18F2520.h>
// Select one of the these settings
//#FUSES NODEBUG
#FUSES DEBUG
#device ICD=TRUE
#FUSES WDT //Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES LPT1OSC
#FUSES MCLR //Master Clear pin enabled
#include <StatusIndicatorLightsDisplay.h>
/* case sensitivity */
#case
#define Version "1.0.0"
#define 1MSCLICKS 1000 // 2000 = (.001 sec)/(4/CLOCKSP==8000000)
// Must be a divide by 4 somewhere
// Number of Ticks in 1ms
#define TIMER001MS 65536-1MSCLICKS // Interrupts on overflow
#include <string.h>
#include <stdlib.h>
// Stores the version
const char strVersion[] = Version;
#FUSES INTRC_IO
#define CLOCKSP 8000000
#use delay(clock=CLOCKSP,internal)
// These are stored during compile time. Each executable
// has one copy of these variables.
char strCompileDate[] = __DATE__;
char strCompileTime[] = __TIME__;
/* setup the UART on port C pins 6 and 7 */
#USE RS232(BAUD=9600, UART1,PARITY=N,BITS=8,STREAM=PC,ERRORS)
//enable the i2c protocol
#use i2c(Master,Slow,sda=PIN_C4,scl=PIN_C3,restart_wdt)
#define XmtDataAvailable (XmtWriteIndex != XmtReadIndex) // indicates a char is available in Xmt ring buffer
#define RcvDataAvailable (RcvWriteIndex != RcvReadIndex) // indicates a char is available in Rcv ring buffer
int8 CRC = 0; //Byte to store the calculated CRC
int8 Stations1_4 = 0; //Byte to store the radio/phone status of stations 1-4
int8 Stations5_8 = 0; //Byte to store the radio/phone status of stations 5-8
int8 Stations9_11 = 0; //Byte to store the radio/phone status of stations 9-11
int8 Stations12_14 = 0; //Byte to store the radio/phone status of stations 12-14
int8 RcvdCRC = 0; //Byte to store the received CRC to compare to what it should be
int16 ResponseTimeoutCounter = RESPONSE_TIMEOUT_RESET_COUNT;
bool bUpdateStatusFlag = FALSE; //Flag to indicate the status needs to be updated
bool bQueryStatusFlag = FALSE; //Flag to indicate the status only needs to be queried
bool bResponseTimeout = FALSE;
// Rcv Com Port Ring buffer
char RcvComPortBuffer[MAX_NUM_RCV_CHARS];
//Searched through if there was a CRC error
char RcvBackupComPortBuffer[MAX_NUM_RCV_CHARS];
// Read and write index always point to next place to read or write
// So buffer is empty if they are =. And is full if write index is
// one behind read index.
unsigned int RcvWriteIndex=0;
unsigned int RcvReadIndex=0;
unsigned int RcvBackupWriteIndex=0;
unsigned int RcvBackupReadIndex=0;
unsigned int RcvBackupCurrentIndex=0;
// Xmt Com Port Ring buffer
char XmtComPortBuffer[MAX_NUM_XMT_CHARS];
// Read and write index always point to next place to read or write
// So buffer is empty if they are =. And is full if write index is
// one behind read index.
unsigned int XmtWriteIndex=0;
unsigned int XmtReadIndex=0;
//Used to make sure only one command is received at a time
int8 SendUpdateCounter = SEND_UPDATE_COUNTER_RESET_COUNT;
int8 RcvUpdateCounter = RCV_UPDATE_COUNTER_RESET_COUNT;
int8 SendQueryCounter = SEND_QUERY_COUNTER_RESET_COUNT;
int8 RcvQueryCounter = RCV_QUERY_COUNTER_RESET_COUNT;
char command = ' ';
char TempBuffer[33];
//============================================================================
// Name: _wr_()
// Description ISR for Empty Transmission Buffer
// Inputs: Serial Port 1 interrupt
// Outputs: External
// Return: None
// Interaction: Reads chars from Xmt Com Port ring buffer and writes to com port
// ===========================================================================
#INT_TBE
void _wr_()
{
if((SendUpdateCounter!=0)&&(SendQueryCounter!=0))
{
while(XmtDataAvailable)
{
// Read char from buffer & write to Com Port
putc(*(char*)(XmtComPortBuffer+XmtReadIndex++));
// Check for modulo of index
if (XmtReadIndex == MAX_NUM_XMT_CHARS)
{
XmtReadIndex = 0;
}
//If sending update information
//Counter used to ensure only one command is sent
if(bUpdateStatusFlag==TRUE)
{
SendUpdateCounter--;
}
//If sending query information
//Counter used to ensure only one command is sent
if(bQueryStatusFlag==TRUE)
{
SendQueryCounter--;
}
}
}
else
{
disable_interrupts(INT_TBE);
}
return;
}
//============================================================================
// Name: _rd_()
// Description ISR for Received chars on Com Port
// Inputs: Serial Port 1 interrupt
// Outputs: None
// Return: None
// Interaction: Writes chars to Rcv Com Port Ring buffer
// ===========================================================================
#INT_RDA
void _rd_()
{
ResetRcvUpdateCounter();
ResetRcvQueryCounter();
ResetResponseTimeoutCounter();
bResponseTimeout = FALSE;
//Loop until a full command response is received
while((RcvUpdateCounter>0)&&(RcvQueryCounter>0)&&(bResponseTimeout == FALSE))
{
//If byte in receive buffer, otherwise wait until a new byte arrives
if(kbhit(PC)== TRUE)
{
char ch=fgetc(PC);
if (ch == '!')
{
bUpdateStatusFlag = TRUE;
bQueryStatusFlag = FALSE;
}
else if (ch == '#')
{
bUpdateStatusFlag = FALSE;
bQueryStatusFlag = TRUE;
}
unsigned int WorkingRcvWriteIndex=RcvWriteIndex;
// Check for modulo
if (++WorkingRcvWriteIndex == MAX_NUM_RCV_CHARS)
{
WorkingRcvWriteIndex = 0;
}
// Check for Buffer full. If full, dont write char
if (WorkingRcvWriteIndex != RcvReadIndex)
{
// Write char to buffer
*(char*)(RcvComPortBuffer+RcvWriteIndex) = ch;
*(char*)(RcvBackupComPortBuffer+RcvWriteIndex) = ch;
// Set it to new position
RcvWriteIndex = WorkingRcvWriteIndex;
RcvBackupWriteIndex = WorkingRcvWriteIndex;
}
//Only wait for more incoming data until a one command is received
if(bUpdateStatusFlag==TRUE)
{
RcvUpdateCounter--;
}
if(bQueryStatusFlag==TRUE)
{
RcvQueryCounter--;
}
}
else
{
if (--ResponseTimeoutCounter == 0)
{
bResponseTimeout = TRUE;
}
}
}
return;
}
//============================================================================
// Name: Setup()
// Description Initializes HW & SW
// Inputs: None
// Outputs: None
// Return: None
// Interaction: Sets up ADC, timers, interrupts, ports
//
// ===========================================================================
void setup()
{
// Empty
while(kbhit(PC))
{
fgetc(PC);
}
// This sets up which port to sample next. Obviously, only 1 choice
// here, so never has to change.
set_adc_channel(0);
delay_us(25);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
// Internal Clock, 8000000
// Divide by 4 to get ips => 0.5 usec
// 0.5 usec * 2 = 1 usec
// for 1 ms = 2 usec * 500
// For a 1 ms timer, set timer to 65566 - 500
// Reset these flags in case it was a watchdog timeout & state unknown
RcvWriteIndex=0;
RcvReadIndex=0;
XmtWriteIndex=0;
XmtReadIndex=0;
All_Lights_On();
All_Lights_Off();
//Make sure Xmit & Rcv RS232 buffers are empty
RcvReadIndex=RcvWriteIndex;
XmtReadIndex=XmtWriteIndex;
enable_interrupts(INT_RDA); // Enable Receive interrupt
enable_interrupts(GLOBAL);
//Don't enable transmit buffer interrupt until data available in buffer
disable_interrupts(INT_TBE);
return;
}
void main()
{
setup();
for(;;)
{
if(RcvDataAvailable)
{
if (bResponseTimeout == TRUE)
{
while (RcvDataAvailable)
{
// Read Command from buffer
command = *(char*)(RcvComPortBuffer+RcvReadIndex++);
}
}
else
{
// Read Command from buffer
command = *(char*)(RcvComPortBuffer+RcvReadIndex++);
// Check for modulo of index
if (RcvReadIndex == MAX_NUM_RCV_CHARS)
{
RcvReadIndex = 0;
}
if (command == '#')
{
QueryCommand();
}
else if (command == '!')
{
UpdateCommand();
}
}
}
}
}
void QueryCommand(void)
{
ResetSendUpdateCounter();
ResetRcvUpdateCounter();
ResetSendQueryCounter();
ResetRcvQueryCounter();
CRC = 0;
CalculateCRC(Stations1_4);
CalculateCRC(Stations5_8);
CalculateCRC(Stations9_11);
CalculateCRC(Stations12_14);
send_byte('#');
send_byte(Stations1_4);
send_byte(Stations5_8);
send_byte(Stations9_11);
send_byte(Stations12_14);
send_byte(CRC);
enable_interrupts(INT_TBE);
}
void UpdateCommand(void)
{
//Read received values to compare to actual values
Stations1_4 = *(char*)(RcvComPortBuffer+RcvReadIndex++);
// Check for modulo of index
if (RcvReadIndex == MAX_NUM_RCV_CHARS)
{
RcvReadIndex = 0;
}
Stations5_8 = *(char*)(RcvComPortBuffer+RcvReadIndex++);
// Check for modulo of index
if (RcvReadIndex == MAX_NUM_RCV_CHARS)
{
RcvReadIndex = 0;
}
Stations9_11 = *(char*)(RcvComPortBuffer+RcvReadIndex++);
// Check for modulo of index
if (RcvReadIndex == MAX_NUM_RCV_CHARS)
{
RcvReadIndex = 0;
}
Stations12_14 = *(char*)(RcvComPortBuffer+RcvReadIndex++);
// Check for modulo of index
if (RcvReadIndex == MAX_NUM_RCV_CHARS)
{
RcvReadIndex = 0;
}
RcvdCRC = *(char*)(RcvComPortBuffer+RcvReadIndex++);
// Check for modulo of index
if (RcvReadIndex == MAX_NUM_RCV_CHARS)
{
RcvReadIndex = 0;
}
//Calculate what received CRC should be with received data
//to check for corruption of data
CRC = 0;
CalculateCRC(Stations1_4);
CalculateCRC(Stations5_8);
CalculateCRC(Stations9_11);
CalculateCRC(Stations12_14);
//if received CRC does not match with received data
if (RcvdCRC != CRC)
{
//Parse through received data again to search for starting character
//to attempt to get back in sync
RcvBackupCurrentIndex = RcvBackupReadIndex;
command = *(char*)(RcvBackupComPortBuffer+RcvBackupReadIndex++);
// Check for modulo of index
if (RcvBackupReadIndex == MAX_NUM_RCV_CHARS)
{
RcvBackupReadIndex = 0;
}
//while a starting character hasn't been found and we haven't searched
//through the whole buffer yet
while ((command != '#')&&(RcvBackupReadIndex != RcvBackupCurrentIndex))
{
if (RcvBackupReadIndex == MAX_NUM_RCV_CHARS)
{
RcvBackupReadIndex = 0;
}
command = *(char*)(RcvBackupComPortBuffer+RcvBackupReadIndex++);
}
//if a starting character was successfully found
if (command == '#')
{
//read received values to compare to actual values one more time
Stations1_4 = *(char*)(RcvBackupComPortBuffer+RcvBackupReadIndex++);
// Check for modulo of index
if (RcvBackupReadIndex == MAX_NUM_RCV_CHARS)
{
RcvBackupReadIndex = 0;
}
Stations5_8 = *(char*)(RcvBackupComPortBuffer+RcvBackupReadIndex++);
// Check for modulo of index
if (RcvBackupReadIndex == MAX_NUM_RCV_CHARS)
{
RcvBackupReadIndex = 0;
}
Stations9_11 = *(char*)(RcvBackupComPortBuffer+RcvBackupReadIndex++);
// Check for modulo of index
if (RcvBackupReadIndex == MAX_NUM_RCV_CHARS)
{
RcvBackupReadIndex = 0;
}
Stations12_14 = *(char*)(RcvBackupComPortBuffer+RcvBackupReadIndex++);
// Check for modulo of index
if (RcvBackupReadIndex == MAX_NUM_RCV_CHARS)
{
RcvBackupReadIndex = 0;
}
RcvdCRC = *(char*)(RcvBackupComPortBuffer+RcvBackupReadIndex++);
// Check for modulo of index
if (RcvBackupReadIndex == MAX_NUM_RCV_CHARS)
{
RcvBackupReadIndex = 0;
}
//Calculate what received CRC should be with received data
//to check for corruption of data
CRC = 0;
CalculateCRC(Stations1_4);
CalculateCRC(Stations5_8);
CalculateCRC(Stations9_11);
CalculateCRC(Stations12_14);
//If CRC is still inaccurate, update sign data
if (RcvdCRC != CRC)
{
ResetSendUpdateCounter();
ResetRcvUpdateCounter();
ResetSendQueryCounter();
ResetRcvQueryCounter();
send_byte('!');
send_byte('N');
send_byte(';');
enable_interrupts(INT_TBE);
}
}
}
else
{
#ifdef DEV_BOARD
Stations1_4 = Stations1_4^255;
Stations5_8 = Stations5_8^255;
Stations9_11 = Stations9_11^255;
Stations12_14 = Stations12_14^255;
#endif
UpdateLights();
#ifdef DEV_BOARD
Stations1_4 = Stations1_4^255;
Stations5_8 = Stations5_8^255;
Stations9_11 = Stations9_11^255;
Stations12_14 = Stations12_14^255;
#endif
ResetSendUpdateCounter();
ResetRcvUpdateCounter();
ResetSendQueryCounter();
ResetRcvQueryCounter();
send_byte('!');
send_byte('Y');
send_byte(';');
enable_interrupts(INT_TBE);
}
}
//-----------------------------------------------------------------------------
// Name: Init_Port_Extenders
//
// Parameters: None
// Return Value: None
//
// Initializes the i2c port extenders to all outputs and all ports at 0.
//
//-----------------------------------------------------------------------------
void Init_Port_Extenders(void)
{
int address;
int i;
for(i=0;i<8;i++)
{
address = BASE_ADD + i*2; // loop through each 9554A
address = address & WRITE; // ensure write bit is 0
i2c_start(); // start i2c cycle
i2c_write(address); // device address for WRITE
i2c_write(OUT_ADD); // access output port
i2c_write(0); // all ports off
i2c_stop();
i2c_start();
i2c_write(address); // device address for WRITE
i2c_write(CFG_ADD); // write to configuration register
i2c_write(0); // all pins are output;
i2c_stop(); // stop i2c cycle
}
}
//-----------------------------------------------------------------------------
// Name: SendPortData(int address, int data)
//
// Parameters: address The device address
// data The data to write
// Return Value: None
//
// This function sends the output data to the port.
// Address is between 0 and 0xFF.
// Data is from 0 to 7.
//
//-----------------------------------------------------------------------------
void SendPortData(int address, int data)
{
i2c_start(); // start i2c cycle
i2c_write(address); // device address for WRITE
i2c_write(OUT_ADD); // access output port
i2c_write(data); // turn on/off proper bits
i2c_stop();
}
void UpdateLights(void)
{
int i,address;
for(i=0;i<4;i++)
{
address = BASE_ADD + i*2; // loop through each 9554A
address = address & WRITE; // ensure write bit is 0
switch (i)
{
case 0:
SendPortData(address,Stations1_4);
break;
case 1:
SendPortData(address,Stations5_8);
break;
case 2:
SendPortData(address,Stations9_11);
break;
case 3:
SendPortData(address,Stations12_14);
break;
}
}
}
//=====================================================================
// Name: CalculateCRC
// Description Calculate the CRC to send with the data
// Inputs: None
// Outputs: None
// Return: None
// Interaction:
// ====================================================================
void CalculateCRC(int data)
{
int i = (data ^ CRC) & 0xFF;
if(i & 1)
{
CRC ^= 0x5E;
}
if(i & 2)
{
CRC ^= 0xBC;
}
if(i & 4)
{
CRC ^= 0x61;
}
if(i & 8)
{
CRC ^= 0xC2;
}
if(i & 0x10)
{
CRC ^= 0x9D;
}
if(i & 0x20)
{
CRC ^= 0x23;
}
if(i & 0x40)
{
CRC ^= 0x46;
}
if(i & 0x80)
{
CRC ^= 0x8C;
}
}
// ====================================================================
// Name: GetCompileDate()
// Description: Used to retrieve the compile date of the executable
//
// Inputs: None
//
// Outputs: None
//
// Return: The Compile Data in a string
//
// Interaction: None
// ====================================================================
//
char* GetCompileDateTime(void)
{
char* strDateTime = &(TempBuffer[0]);
strcpy(strDateTime,strCompileDate);
strcpy(strDateTime+strlen(strDateTime),",");
strcpy(strDateTime+strlen(strDateTime),strCompileTime);
return strDateTime;
}
//=====================================================================
// Name: WriteStringToXmitter
// Description Parse through a string, adding each bit to the Xmt Buffer
// Inputs: None
// Outputs: None
// Return: None
// Interaction:
// ====================================================================
void WriteStringToXmitter(char* strChars)
{
int length = strlen(strChars);
int i=0;
for (i=0;i<length;i++)
{
send_byte(strChars[i]);
}
return;
}
//============================================================================
// Name: send_byte(byte)
// Description adds bytes to Xmt Buffer
// Inputs: Byte to send
// Outputs: None
// Return: None
// Interaction: Enables transmit buffer interrupt
// ===========================================================================
void send_byte(txbyte)
{
unsigned int WorkingXmtWriteIndex=XmtWriteIndex;
// Check for modulo of index
if (++WorkingXmtWriteIndex == MAX_NUM_XMT_CHARS)
{
WorkingXmtWriteIndex = 0;
}
// Check for Buffer full. If full, dont write char.
if (WorkingXmtWriteIndex != XmtWriteIndex)
{
// Write Response to Buffer
*(char*)(XmtComPortBuffer+XmtWriteIndex) = txbyte;
// Set it to new location
XmtWriteIndex=WorkingXmtWriteIndex;
}
return;
}
//-----------------------------------------------------------------------------
// Name: All_Lights_Off
//
// Parameters: None
// Return Value: None
//
// This function turns off all port bits.
//
//-----------------------------------------------------------------------------
void All_Lights_Off(void)
{
int address;
int i;
for(i=0;i<4;i++)
{
address = BASE_ADD + i*2; // loop through each 9554A
address = address & WRITE; // ensure write bit is 0
SendPortData(address, LIGHTS_OFF); // device address for WRITE
}
}
//-----------------------------------------------------------------------------
// Name: All_Lights_On
//
// Parameters: None
// Return Value: None
//
// This function turns on all port bits.
//
//-----------------------------------------------------------------------------
void All_Lights_On(void)
{
int address;
int i;
for(i=0;i<4;i++)
{
address = BASE_ADD + i*2; // loop through each 9554A
address = address & WRITE; // ensure write bit is 0
SendPortData(address, LIGHTS_ON); // device address for WRITE
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 14, 2012 11:45 am |
|
|
The first two things I would do to diagnose this problem are:
1. Disable the WDT (use the NOWDT fuse).
2. Remove these two lines:
#FUSES DEBUG
#device ICD=TRUE |
|
|
wiseacre
Joined: 14 Jun 2012 Posts: 9
|
|
Posted: Thu Jun 14, 2012 1:04 pm |
|
|
Tried these and am still having the same problem. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 14, 2012 1:17 pm |
|
|
Remove NOBROWNOUT and add the BROWNOUT fuse.
What's your PIC's Vdd voltage ?
What's your programmer ?
And your compiler version ? |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Jun 14, 2012 1:33 pm |
|
|
** what cha got on your MCLR pin ??
for sure is there no way is that pin getting a "program level" voltage applied during runtime ?? |
|
|
wiseacre
Joined: 14 Jun 2012 Posts: 9
|
|
Posted: Thu Jun 14, 2012 2:38 pm |
|
|
Used BROWNOUT fuse and still not working.
PIC Vdd voltage is 5.0V.
Programmer is CCSLoad using both ICD-U40 and ICD-U64.
CCSLoad software version: 4.037
firmware version: 2.93
no way the pin is getting program level voltage. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Thu Jun 14, 2012 2:47 pm |
|
|
Other classic things are ground/power connections not properly made. Chip gets power from the ICD/programmer, but not when these are disconnected.
Best Wishes |
|
|
wiseacre
Joined: 14 Jun 2012 Posts: 9
|
|
Posted: Thu Jun 14, 2012 2:49 pm |
|
|
Everything is connected properly. It works just fine with any other program, just not the one posted here. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
wiseacre
Joined: 14 Jun 2012 Posts: 9
|
|
Posted: Thu Jun 14, 2012 2:59 pm |
|
|
Oops, my apologies. I copied it, just must've forgotten to paste it.
CCS PCH C Compiler, Version 4.132, xxxxx 14-Jun-12 15:40 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 14, 2012 3:07 pm |
|
|
Well, that version should be OK.
Hardware:
Did you design and build this board ? I mean the circuits and the PCB
board layout. Or did you buy it ?
If I had this problem, I would change out everything: The PIC, the board,
the programmer. If it's on a custom board, I would move it to a generic
Pic eval board, if possible. (Such as a 4-layer PicDem2-Plus, etc).
Software:
I would re-install the compiler.
I would strip down the program, removing most of the code, and see if
the problem still occurs. I would add short printf statements within
the program to identify where it's locking up.
This is actually done from a distance. I'm making all these statements
without having analyzed your posted code in detail. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Fri Jun 15, 2012 1:30 am |
|
|
The code is too long for anybody to look through, especially since we don't 'know' what the external connections actually do.
However there are a couple of dangerous things:
Move the clock fuses, settings, and RS232 declarations _above_ all the includes. Anything that uses timings or RS232, _must_ have these loaded first. The 'safe' layout is:
1) Processor include
2) Fuses
3) Clock settings, RS232, I2C etc.
4) Now the global defines
5) Includes
Some parts can be swapped (the global defines can be after the includes, if the includes don't use any of them, but this is the 'reliable' layout.
You say other code works. Does the other code use the MCLR pin?. One obvious thing would be that this is pulled up by the ICD/programmer, and if there is no pull up on it on the board, then this code has 'MCLR' selected, and would not run...
The RS232 receive code has the classic "I'm going to bu&&er everything else up" design, sitting and effectively locking the processor from doing anything else, until the entire string is received. _Study how to buffer the RS232 and use this interrupt_. The interrupt says 'one character is waiting', and if you want other things to happen, the code in the ISR should just receive one character. If the RS232 line isn't properly connected this will hang the chip completely.
Move all the variable declarations to the start of function blocks. CCS won't complain, and will sometimes let them work, but the results _are unreliable_. Stick to conventional C declarations. Much safer. Also, CCS does not correctly allow values to be initialised with returns from functions at declare time.
If you perform an allocate and declare together:
int8 val=getc();
and do nothing else with 'val', you will get the compiler warning 'variable never used val', yet if instead you perform the declare and the call separately, no such warning, telling you that the compiler is not correctly handling the combined operation. This was a documented limitation of the old compiler, which in recent versions is meant to have been allowed, but still does _not_ work reliably. If you want your code to work, stick to declaring separately....
Best Wishes |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Fri Jun 15, 2012 4:40 am |
|
|
Quote: |
// Select one of the these settings
//#FUSES NODEBUG
#FUSES DEBUG
#device ICD=TRUE
|
This will generate debug code. Debug code WILL NOT run standalone.
To solve this you need to do two things:
1. put the NODEBUG fuse setting in with the rest of the fuses. Do NOT change this to DEBUG. That will automatically be handled by the compiler/IDE.
I use this line with a comment to remind me:
#FUSES NODEBUG //No Debug mode for ICD - this is overridden by #device ICD=TRUE
2. Use #device ICD=TRUE for debug builds. Comment it out for standalone, i.e. normal, non-debug builds.
I have two projects for many of my projects: the top level .c file of both includes the main .c, the only difference being one has #device ICD=TRUE so generates a debug version, the other isn't and build normal, i.e. non-debug, code.
If you try and run debug code as standalone code it simply won't run, or at least your code won't. The debug monitor code will run, and sit waiting to talk to a debugger that isn't there.
Note that with IDC=TRUE the wdt and the brownout detection will be disabled (the compiler overrides the fuses for you). There may be other differences, but I can't remember them off hand.
RF Developer |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri Jun 15, 2012 7:04 am |
|
|
this statement has been bothering me
Quote: |
If I try to reprogram the PIC after doing this, the code won't work. |
reprogramming should result in a full erasure of the pic - this is the most troubling part of all.
i use an EPIC programmer with a nice code read back feature.
AFTER you get your pic into the failed state
have you tried to do a read back of it and COMPARE the hex file to the source you programmed ??
i'd be especially interested in whether the fuses match .......
AND are what you THINK they are |
|
|
wiseacre
Joined: 14 Jun 2012 Posts: 9
|
|
Posted: Fri Jun 15, 2012 7:58 am |
|
|
PCM programmer wrote: | Well, that version should be OK.
Hardware:
Did you design and build this board ? I mean the circuits and the PCB
board layout. Or did you buy it ?
If I had this problem, I would change out everything: The PIC, the board,
the programmer. If it's on a custom board, I would move it to a generic
Pic eval board, if possible. (Such as a 4-layer PicDem2-Plus, etc).
Software:
I would re-install the compiler.
I would strip down the program, removing most of the code, and see if
the problem still occurs. I would add short printf statements within
the program to identify where it's locking up.
This is actually done from a distance. I'm making all these statements
without having analyzed your posted code in detail. |
Hardware: I didn't design the board but a coworker did. We don't have a custom eval board with this PIC that I could move it to.
Software: No status change after all of this.
Ttelmah wrote: | The code is too long for anybody to look through, especially since we don't 'know' what the external connections actually do.
However there are a couple of dangerous things:
Move the clock fuses, settings, and RS232 declarations _above_ all the includes. Anything that uses timings or RS232, _must_ have these loaded first. The 'safe' layout is:
1) Processor include
2) Fuses
3) Clock settings, RS232, I2C etc.
4) Now the global defines
5) Includes
Some parts can be swapped (the global defines can be after the includes, if the includes don't use any of them, but this is the 'reliable' layout.
You say other code works. Does the other code use the MCLR pin?. One obvious thing would be that this is pulled up by the ICD/programmer, and if there is no pull up on it on the board, then this code has 'MCLR' selected, and would not run...
The RS232 receive code has the classic "I'm going to bu&&er everything else up" design, sitting and effectively locking the processor from doing anything else, until the entire string is received. _Study how to buffer the RS232 and use this interrupt_. The interrupt says 'one character is waiting', and if you want other things to happen, the code in the ISR should just receive one character. If the RS232 line isn't properly connected this will hang the chip completely.
Move all the variable declarations to the start of function blocks. CCS won't complain, and will sometimes let them work, but the results _are unreliable_. Stick to conventional C declarations. Much safer. Also, CCS does not correctly allow values to be initialised with returns from functions at declare time.
If you perform an allocate and declare together:
int8 val=getc();
and do nothing else with 'val', you will get the compiler warning 'variable never used val', yet if instead you perform the declare and the call separately, no such warning, telling you that the compiler is not correctly handling the combined operation. This was a documented limitation of the old compiler, which in recent versions is meant to have been allowed, but still does _not_ work reliably. If you want your code to work, stick to declaring separately....
Best Wishes |
Reorganized everything and still the same problem. Yes, the other code uses the MCLR pin. It does have a pull up on the board.
RF_Developer wrote: | This will generate debug code. Debug code WILL NOT run standalone.
To solve this you need to do two things:
1. put the NODEBUG fuse setting in with the rest of the fuses. Do NOT change this to DEBUG. That will automatically be handled by the compiler/IDE.
I use this line with a comment to remind me:
#FUSES NODEBUG //No Debug mode for ICD - this is overridden by #device ICD=TRUE
2. Use #device ICD=TRUE for debug builds. Comment it out for standalone, i.e. normal, non-debug builds.
I have two projects for many of my projects: the top level .c file of both includes the main .c, the only difference being one has #device ICD=TRUE so generates a debug version, the other isn't and build normal, i.e. non-debug, code.
If you try and run debug code as standalone code it simply won't run, or at least your code won't. The debug monitor code will run, and sit waiting to talk to a debugger that isn't there.
Note that with IDC=TRUE the wdt and the brownout detection will be disabled (the compiler overrides the fuses for you). There may be other differences, but I can't remember them off hand.
RF Developer |
I understand that. I have been running it just in debug mode to continue writing the code and had copied the code from that point. When I try and program the chip, I make sure I have the NODEBUG Fuse set. Thanks, though.
asmboy wrote: | this statement has been bothering me
Quote: |
If I try to reprogram the PIC after doing this, the code won't work.
|
reprogramming should result in a full erasure of the pic - this is the most troubling part of all.
i use an EPIC programmer with a nice code read back feature.
AFTER you get your pic into the failed state
have you tried to do a read back of it and COMPARE the hex file to the source you programmed ??
I'd be especially interested in whether the fuses match .......
AND are what you THINK they are |
I put the PIC in failed state, read back the hex file, compared it to the hex file I originally programmed the PIC with and they are very different. The failed state hex file includes most of the original hex file, but has a ton added to it as well. Most of it is 'FFFF', but other values are included as well. |
|
|
|
|
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
|