pic24_util.c

Go to the documentation of this file.
00001 /*
00002  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
00003  * All rights reserved.
00004  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
00005  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
00006  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
00007  *
00008  * Permission to use, copy, modify, and distribute this software and its
00009  * documentation for any purpose, without fee, and without written agreement is
00010  * hereby granted, provided that the above copyright notice, the following
00011  * two paragraphs and the authors appear in all copies of this software.
00012  *
00013  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
00014  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
00015  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
00016  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00017  *
00018  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00019  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00020  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
00021  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
00022  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
00023  *
00024  * Please maintain this header in its entirety when copying/modifying
00025  * these files.
00026  *
00027  *
00028  */
00029 
00030 
00031 
00032 // Documentation for this file. If the \file tag isn't present,
00033 // this file won't be documented.
00039 #include "pic24_all.h"
00040 #include <stdio.h>        // To define NULL
00041 
00042 
00043 #if !USE_HEARTBEAT && !defined(__DOXYGEN__)
00044 // No heartbeat; instead, just define empty functions.
00045 void configHeartbeat(void) {
00046 }
00047 
00048 void doHeartbeat(void) {
00049 }
00050 
00051 void toggleHeartbeat(void) {
00052 }
00053 #else
00054 
00067 uint32 u32_heartbeatCount;
00071 static uint32 u32_heartbeatMax;
00072 
00073 
00078 void configHeartbeat(void) {
00079   CONFIG_HB_LED();
00080   /* long enough to see LED toggle. Incrementing the heartbeat
00081   takes several cycles - CYCLES_PER_MS used as the multiplier so that
00082   we are tied to FCY
00083   */
00084   u32_heartbeatMax = CYCLES_PER_MS * 10;
00085   u32_heartbeatCount = 0;
00086   HB_LED = 0;   // Turn LED off to show we started running
00087   doHeartbeat();    // do Heartbeat   at least once
00088 }
00089 
00094 void doHeartbeat(void) {
00095   u32_heartbeatCount++;
00096   if (u32_heartbeatCount > u32_heartbeatMax) {
00097     toggleHeartbeat();
00098     u32_heartbeatCount = 0;
00099   }
00100 }
00101 
00102 
00106 void toggleHeartbeat(void) {
00107   HB_LED = !HB_LED;
00108 }
00110 #endif
00111 
00116 static _PERSISTENT const char* sz_lastError;
00120 _PERSISTENT char* sz_lastTimeoutError;
00121 
00122 #ifndef __PIC24F__
00123 
00130 static _PERSISTENT INTTREGBITS INTTREGBITS_last;
00136 #define u16_INTTREGlast BITS2WORD(INTTREGBITS_last)
00137 #else
00138 static uint16 u16_INTTREGlast;
00139 #endif
00140 
00146 void _ISR _DefaultInterrupt(void) {
00147 #ifndef __PIC24F__
00148   // Record the interrupt vector and priority of the
00149   // unhandled interrupt.
00150   u16_INTTREGlast = INTTREG;
00151 #else
00152   // Any non-zero value causes reportError to report
00153   // this. This register doesn't exist on the PIC24F.
00154   u16_INTTREGlast = 1;
00155 #endif
00156   reportError("Unhandled interrupt, ");
00157 }
00158 
00159 
00167 void reportError(const char* sz_errorMessage) {
00168   //ignore if a previous error has already been triggerred
00169   if (sz_lastError == NULL) {
00170     sz_lastError = sz_errorMessage;
00171     asm ("reset");
00172   }
00173 }
00174 
00180 uint32 readProgramMemory(uint32 u32_address) {
00181   uint16 u16_offset = u32_address;
00182   TBLPAG = u32_address >> 16;
00183   return ( ((uint32) __builtin_tblrdh(u16_offset)) << 16) |
00184          __builtin_tblrdl(u16_offset);
00185 }
00186 
00192 void checkDeviceAndRevision(void) {
00193 #ifdef SIM
00194   outString("**** SIMULATION MODE: cannot read device and revision ID ****\n");
00195 #else
00196   uint32 devID = readProgramMemory(DEV_ID_LOCATION);
00197   uint32 revision = readProgramMemory(REVISION_LOCATION);
00198   uint8 correctChip = 1;
00199   char* devIDStr = "unknown";
00200   char* revisionStr = "unknown";
00201 
00202   if (devID == DEV_ID)
00203     devIDStr = DEV_ID_STR;
00204   else
00205     correctChip = 0;
00206 
00207   switch (revision) {
00208     case EXPECTED_REVISION1 :
00209       revisionStr = EXPECTED_REVISION1_STR;
00210       break;
00211 #ifdef EXPECTED_REVISION2
00212     case EXPECTED_REVISION2 :
00213       revisionStr = EXPECTED_REVISION2_STR;
00214       break;
00215 #endif
00216 #ifdef EXPECTED_REVISION3
00217     case EXPECTED_REVISION3 :
00218       revisionStr = EXPECTED_REVISION3_STR;
00219       break;
00220 #endif
00221 #ifdef EXPECTED_REVISION4
00222     case EXPECTED_REVISION4 :
00223       revisionStr = EXPECTED_REVISION4_STR;
00224       break;
00225 #endif
00226 #ifdef EXPECTED_REVISION5
00227     case EXPECTED_REVISION5 :
00228       revisionStr = EXPECTED_REVISION5_STR;
00229       break;
00230 #endif
00231     default :
00232       correctChip = 0;
00233       break;
00234   }
00235 
00236   outString("Device ID = ");
00237   outUint32(devID);
00238   outString(" (");
00239   outString(devIDStr);
00240   outString("), revision ");
00241   outUint32(revision);
00242   outString(" (");
00243   outString(revisionStr);
00244   outString(")\n");
00245 
00246   if (!correctChip)
00247     outString("\n\n"
00248               "*****************************************************\n"
00249               "* WARNING - this program was compiled for the wrong *\n"
00250               "* chip or for an unknown revision of this chip!     *\n"
00251               "* This program may produce unexpected behvior! Edit *\n"
00252               "* the header files to properly define this chip or  *\n"
00253               "* revision and to insure correct operation.         *\n"
00254               "*                                                   *\n"
00255               "* NOTE: If this was compiled for the correct chip,  *\n"
00256               "* and only occurs at power-on (not during a MCLR    *\n"
00257               "* reset, verify that AVDD and AVSS are connected.   *\n"
00258               "* On the PIC24H32GP202, not connecting AVDD         *\n"
00259               "* produces this message only at power-up.           *\n"
00260               "*****************************************************\n");
00261 #endif
00262 }
00263 
00267 void checkOscOption(void) {
00268   uint8 u8_x;
00269 
00270   u8_x = _COSC;         // Get current oscillator setting
00271   switch (u8_x) {
00272     case 0:
00273       outString("Fast RC Osc\n");
00274       break;
00275     case 1:
00276       outString("Fast RC Osc with PLL\n");
00277       break;
00278     case 2:
00279       outString("Primary Osc (XT, HS, EC)\n");
00280       break;
00281     case 3:
00282       outString("Primary Osc (XT, HS, EC) with PLL\n");
00283       break;
00284     case 4:
00285       outString("Secondary Osc\n");
00286       break;
00287     case 5:
00288       outString("Low Power RC Osc\n");
00289       break;
00290 #if defined(__PIC24H__) || defined(__dsPIC33F__)
00291     case 6:
00292       outString("Fast RC Osc/16\n");
00293       break;
00294     case 7:
00295       outString("Fast RC Osc/N\n");
00296       break;
00297 #elif ( defined(__PIC24F__) || defined(__PIC24FK__) )
00298     case 7 :
00299       outString("Fast RC Osc with Postscale");
00300       break;
00301 #else
00302 #error Unknown processor
00303 #endif
00304     default :
00305       reportError("Unknown oscillator type.");
00306       break;
00307   }
00308 }
00309 
00314 void printResetCause(void) {
00315   uint8 u8_resetIdentified;
00316 
00317   u8_resetIdentified = 0;
00318   if (_SLEEP) {
00319     outString("\nDevice has been in sleep mode\n");
00320     _SLEEP = 0;
00321   }
00322   if (_IDLE) {
00323     outString("\nDevice has been in idle mode\n");
00324     _IDLE = 0;
00325   }
00326   outString("\nReset cause: ");
00327   if (_POR) {
00328     u8_resetIdentified = 1;
00329     outString("Power-on.\n");
00330     _POR = 0;
00331     _BOR = 0; //clear both
00332     // Set the values below, which reset all the
00333     // error reporting variables to indicate that
00334     // no error has (yet) occurred.
00335     sz_lastError = NULL;
00336     sz_lastTimeoutError = NULL;
00337     u16_INTTREGlast = 0;
00338   } else {
00339     //non-POR
00340     if (_SWR) {
00341       outString("Software Reset.\n");
00342       u8_resetIdentified = 1;
00343       _SWR = 0;
00344       _EXTR = 0;  //also sets the EXTR bit
00345     }
00346     if (_WDTO) {
00347       u8_resetIdentified = 1;
00348       outString("Watchdog Timeout: ");
00349       if (sz_lastTimeoutError != NULL) {
00350         outString(sz_lastTimeoutError);
00351       }
00352       outString("\n");
00353       _WDTO = 0;
00354       _EXTR = 0; //also sets the EXTR bit
00355     }
00356     if (_EXTR) {
00357       u8_resetIdentified = 1;
00358       outString("MCLR assertion.\n");
00359       _EXTR = 0;
00360     }
00361     if (_BOR) {
00362       u8_resetIdentified = 1;
00363       outString("Brown-out.\n");
00364       _BOR = 0;
00365     }
00366     if (_TRAPR) {
00367       u8_resetIdentified = 1;
00368       outString("Trap Conflict.\n");
00369       _TRAPR = 0;
00370     }
00371     if (_IOPUWR) {
00372       u8_resetIdentified = 1;
00373       outString("Illegal Condition.\n");
00374       _IOPUWR = 0;
00375     }
00376 #ifdef _CM
00377     if (_CM) {
00378       u8_resetIdentified = 1;
00379       outString("Configuration Mismatch.\n");
00380       _CM = 0;
00381     }
00382 #endif
00383   } //end non-POR
00384 
00385   if (!u8_resetIdentified) {
00386     outString("Unknown reset.\n");
00387   }
00388   if (sz_lastError != NULL) {
00389     outString("Error trapped: ");
00390     outString(sz_lastError);
00391     if (u16_INTTREGlast != 0) {
00392 #if ( defined(__PIC24H__) || defined(__dsPIC33F__) )
00393       outString("Priority: ");
00394       outUint8(INTTREGBITS_last.ILR);
00395       outString(", Vector number: ");
00396       outUint8(INTTREGBITS_last.VECNUM);
00397 #else
00398       outString("Unknown priority/vector");
00399 #endif
00400     }
00401     outString("\n\n");
00402     sz_lastError = NULL;
00403     u16_INTTREGlast = 0;
00404   }
00405 
00406   checkDeviceAndRevision();
00407   checkOscOption();
00408 }
00409 
00424 //this function is processor specific
00425 #if (defined(__PIC24HJ32GP202__) || \
00426    defined(__PIC24FJ64GA002__))
00427 void configPinsForLowPower(void) {
00428   // Configure all digital I/O pins for input
00429   TRISB = 0xFFFF;
00430   TRISA = 0xFFFF;
00431   // Configure all analog pins as digital I/O
00432 #if defined(__PIC24F__)
00433   AD1PCFG = 0xFFFF;
00434 #elif defined(__PIC24H__)
00435   AD1PCFGL = 0xFFFF;
00436 #else
00437 #error Unknown processor
00438 #endif
00439   // Enable all pullups, except those which clocks are
00440   // connected to.
00441 
00442   // CN31-CN16 enable, based on if primary osc is used
00443   // or not.
00446 #if (FNOSC_SEL == FNOSC_PRI) || (FNOSC_SEL == FNOSC_PRIPLL)
00447 #if (POSCMD_SEL == POSCMD_EC)
00448   // The external oscillator driving the clock is on OSCI,
00449   // which is CN30. Don't enable the pullup on this pin to
00450   // avoid interfering with it.
00451   // Note that CNPU2 covers CN31 to CN16.
00453   CNPU2 = 0xBFFF;
00454 #else
00455   // The crystal driving the primary oscillator is on OSCI/OSCO,
00456   // which is CN30 and CN29. Don't enable pullups on these pins,
00457   // since that will prevent the crystal from oscillating.
00458   // Note that CNPU2 covers CN31 to CN16.
00459   CNPU2 = 0x9FFF;
00460 #endif // #if (POSCMD_SEL == POSCMD_EC)
00461 #else // The primary oscillator is not selected
00462   // Turn on all the pull-ups
00463   CNPU2 = 0xFFFF;
00464 #endif
00465 
00466   // CN15-CN0 enable, based on if secondary osc is used
00467   // or not.
00468 #if (FNOSC_SEL == FNOSC_SOSC)
00469   // The crystal driving the secondary oscillator is on
00470   // SOSCI/SOSCO, which is CN1 and CN0.
00472   CNPU1 = 0xFFFC;
00473 #else
00474   CNPU1 = 0xFFFF;
00475 #endif
00476 }
00477 #else
00478 #warning Using dummy function for configPinsForLowPower() in 'common/pic24_util.c'
00479 void configPinsForLowPower(void) {
00480 }
00481 #endif
00482 
00483 
00493 void configBasic(const char* sz_helloMsg) {
00494   configHeartbeat();
00495   configClock();
00496   configDefaultUART(DEFAULT_BAUDRATE);
00497   printResetCause();
00498   outString(sz_helloMsg);
00499 }
00500 
00501 
00506 uint32 roundFloatToUint32(float f_x) {
00507   uint32 u32_y;
00508 
00509   u32_y = f_x;
00510   if ((f_x - u32_y) < 0.5) return u32_y;
00511   else return u32_y+1;
00512 }
00513 
00515 uint16 roundFloatToUint16(float f_x) {
00516   uint16 u16_y;
00517 
00518   u16_y = f_x;
00519   if ((f_x - u16_y) < 0.5) return u16_y;
00520   else return u16_y+1;
00521 }
00522 
00523 

Generated on Mon Oct 18 07:40:46 2010 for Python-on-a-chip by  doxygen 1.5.9