我正在使用带有编译器 XC16 的 PIC30F4011。我注意到局部变量的赋值不起作用,但是如果我将变量声明为全局变量,它就起作用了。
在下面的函数中,在赋值语句: 之后addr = b_flashStart;
,addr
应该是0x1600
,但实际上是0
。
uint16_t __attribute__((section("boot"))) b_calcCrc(void)
{
uint16_t addrU = 0;
uint16_t crcFlash;
uint16_t index = 0;
uint16_t addr = 0;
addrU = 0x0000;
addr = b_flashStart;
crcFlash = 0xFFFF;
for(addr = b_flashStart; addr < 0x7fc0/*b_flashEnd*/; addr += 0x0040)
{
b_flashRowRead( addrU, addr, flashReadBuffer ); // Row of 32 pairs
for(index = 0; index < 0x40;)
{
b_temp = flashReadBuffer[index++];
crcFlash = b_crc16( crcFlash, b_temp );
b_temp = flashReadBuffer[index++];
crcFlash = b_crc16( crcFlash, b_temp );
b_temp = flashReadBuffer[index++];
crcFlash = b_crc16( crcFlash, b_temp );
b_temp = flashReadBuffer[index++];
crcFlash = b_crc16( crcFlash, b_temp );
}
}
return crcFlash;
}
这是整个文件:
/******************************************************************************/
/* Files to Include */
/******************************************************************************/
/* Device header file */
#include <xc.h>
#include <stdint.h> // Includes uint16_t definition
#include <stdbool.h> // Includes true/false definition
#define FCY 20000000UL
#include <libpic30.h>
/******************************************************************************/
// Programming format Memory Map
// -----------------
// | 0x0000 |
// | 0x0002 | Boot vector
// | 0x0004 | Unlock & write vector
// | |
// | |
// | Boot Block | (this program)
// | |
// | 0x1000 | Re-mapped Reset Vector
// | 0x0600 | Re-mapped Interrupt Vector table
// | |
// | | |
// | |
// | 0X1000 | User program space
// | |
// | | |
// | |
// | 0xFFFE |
// -----------------
//
/*****************************************************************************/
#define MINOR_VERSION 0x00 // Version
#define MAJOR_VERSION 0x01
#define RC_DLE 0x01
#define RC_STX 0x02
#define STX 0x023 // use # instead
#define ETX 0x04
#define DLE 0x05
/*****************************************************************************/
#define CHKSUM 0x00 // Checksum accumulator
#define COUNTER 0x01 // General counter
#define ABTIME_H 0x02
#define ABTIME_L 0x03
#define RXDATA 0x04
#define TXDATA 0x05
#define COMMAND 0x02 // Data mapped in receive buffer
#define DATA_COUNT 0x03
#define ADDRESS_L 0x04
#define ADDRESS_H 0x05
#define ADDRESS_UL 0x06
#define ADDRESS_UH 0x07
/*****************************************************************************/
/******************************************************************************/
/* Main Program */
/******************************************************************************/
#define pinBoot PORTBbits.RB3 // Programming flag
//#define pinStby PORTBbits.RB1 // CAN standby
#define bootFlag 1
#define baudConstant 129 // 9600 baud with PLL_8
bool b_processRecord(uint16_t);
uint16_t b_getRecord(void);
void b_writeUART(char ch);
char b_readUART(void);
void b_initUART(void); // Initialize UART 2 to 115200 baud
void b_initCAN(void); // for debugging output - watch on CANAlyzer
void b_sendCAN(void);
void b_bootend(); // jump to application
uint16_t b_crc16(uint16_t crc, uint16_t data);
void b_crcMessage(bool flash, bool eeProm);
uint16_t b_calcCrc(void);
//unsigned int b_eeprom_read_int(unsigned int address);
//unsigned int b_eeprom_write_int(unsigned int address, unsigned int data);
#define b_flashStart 0x1600
#define b_flashEnd 0x7FFF
#define b_eepromStart 0xFC00
#define b_eepromEnd 0xFFFF
#define b_poly 0x8408 // crc16 polynoimial
union CAN
{
uint8_t bytes[256];
uint16_t words[128];
}b_CAN;
union Buffer
{
uint8_t charBuffer[256];
uint16_t wordBuffer[128];
}b;
uint16_t b_receivePointer;
unsigned char b_checksum;
unsigned char b_bufferCANb[8];
unsigned char b_bufferCANw[4];
uint16_t i;
uint16_t testSID;
bool booting = false;
uint16_t b_temp;
static uint16_t flashReadBuffer[256];
//uint16_t b_eepromRead(uint16_t adr);
//void b_eepromWrite(uint16_t adr, uint16_t data);
static uint16_t crc16_calc = 0;
static uint16_t crc16_sv = 0;
void __attribute__((section("boot"))) b_boot(void)
{
uint16_t bufSize;
// uint16_t crc16_calc;
// uint16_t crc16_sv;
ADPCFGbits.PCFG3 = 1; // RB3 set to digital input
TRISBbits.TRISB3 = 1; // Input - Boot Flag
TRISDbits.TRISD0 = 0; //LED
// TRISBbits.TRISB1 = 0; // Output - CAN standby
// pinStby = 0; // make transceiver active
// crc16_sv = b_eeprom_read_int(EEPROM_APP_CRC_ADDR);
crc16_calc = b_calcCrc();
PORTDbits.RD0 = 1;
booting = true;
b_initUART(); // initialize the UART
b_initCAN();
testSID = 0x030; // signal we are in boot mode
b_sendCAN();
b_flashRowRead( 0, 0x7fc0, flashReadBuffer );
crc16_sv = flashReadBuffer[0x3e];
if((pinBoot != bootFlag) && (crc16_sv == crc16_calc)) // if no boot flag - go to user code
b_bootend();
while(booting)
{
bufSize = b_getRecord();
if(pinBoot != bootFlag) b_bootend();
b_processRecord(bufSize);
}
b_bootend();
}
uint16_t checkFlashCrc;
bool __attribute__((section("boot"))) b_processRecord(uint16_t bufSize)
{
// uint16_t flashReadBuffer[256];
uint16_t crcFlash;
uint16_t crcEeprom;
uint16_t index;
uint16_t checkFlashCrc;
uint16_t checkEepromCrc;
bool flashFlag = false;
bool eePromFlag = false;
unsigned char command = b.charBuffer[COMMAND];
uint16_t addrU = ((uint16_t)b.charBuffer[ADDRESS_UH] << 8) & 0xFF00 |
(uint16_t)b.charBuffer[ADDRESS_UL] & 0x00FF;
uint16_t addr = ((uint16_t)b.charBuffer[ADDRESS_H] << 8) & 0xFF00 |
(uint16_t)b.charBuffer[ADDRESS_L] & 0x00FF;
addr = (addr / 2) | ((addrU << 15) & 0x8000); // make it a word address
addrU = addrU / 2;
switch(command)
{
case 0x01: // compute crc
PORTDbits.RD0 = 1;
testSID = 0x31;
b_sendCAN();
checkFlashCrc = b.wordBuffer[2];
checkEepromCrc = b.wordBuffer[3];
// compute eeprom checksum
addrU = 0x007F;
addr = 0xFC00;
crcEeprom = 0xFFFF;
index = b_eepromEnd - b_eepromStart + 1;
for(addr = b_eepromStart; index > 0; index -= 2, addr += 2 ) // skip upper bytes
{
b_temp = b_eePromRead(addrU, addr);
crcEeprom = b_crc16(crcEeprom, b_temp);
}
b_flashRowRead( 0, 0x7fc0, flashReadBuffer );
flashReadBuffer[0x3E] = checkFlashCrc;
b_flashRowWrite(0, 0x7FC0, flashReadBuffer);
b_CAN.bytes[2] = 0xFF;
b_CAN.bytes[3] = 0xFF;
crcFlash = b_calcCrc();
if( crcFlash == checkFlashCrc ) // set check flags
{
// b_eeprom_write_int(EEPROM_APP_CRC_ADDR, crcFlash);
flashFlag = true;
b_CAN.bytes[2] = 0x01;
PORTDbits.RD0 = 0;
}
if( crcEeprom == checkEepromCrc )
{
eePromFlag = true;
b_CAN.bytes[3] = 0x01;
}
b_crcMessage( flashFlag, eePromFlag );
b_CAN.words[2] = crcFlash;
b_CAN.words[3] = crcEeprom;
testSID = 0x0032;
b_sendCAN();
booting = false; // we are done
break;
case 0x02: // write flash
PORTDbits.RD0 = 0;
if( addr >= 0x1600)
{
b_flashRowWrite(addrU, addr, &b.wordBuffer[4]);
}
break;
case 0x03: // erase flash
PORTDbits.RD0 = 1;
if( addr >= 0x1600)
{
b_flashRowErase(addrU, addr);
}
break;
case 0x04: // erase eeprom
b_eePromAllErase(0x007F, 0xFC00);
break;
case 0x05: // write eeprom
if( addrU == 0x007F)
{
b_eePromRowWrite(addrU, addr, &b.wordBuffer[4]);
}
break;
default:
break;
}
return true;
}
uint16_t __attribute__((section("boot"))) b_calcCrc(void)
{
uint16_t addrU = 0;
uint16_t crcFlash;
uint16_t index = 0;
uint16_t addr = 0;
addrU = 0x0000;
addr = b_flashStart;
crcFlash = 0xFFFF;
for(addr = b_flashStart; addr < 0x7fc0/*b_flashEnd*/; addr += 0x0040)
{
b_flashRowRead( addrU, addr, flashReadBuffer ); // Row of 32 pairs
for(index = 0; index < 0x40;)
{
b_temp = flashReadBuffer[index++];
crcFlash = b_crc16( crcFlash, b_temp );
b_temp = flashReadBuffer[index++];
crcFlash = b_crc16( crcFlash, b_temp );
b_temp = flashReadBuffer[index++];
crcFlash = b_crc16( crcFlash, b_temp );
b_temp = flashReadBuffer[index++];
crcFlash = b_crc16( crcFlash, b_temp );
}
}
#if 0
b_flashRowRead( addrU, addr, flashReadBuffer ); // Row of 32 pairs
for(index = 0; index < 0x3D;)
{
b_temp = flashReadBuffer[index++];
crcFlash = b_crc16( crcFlash, b_temp );
b_temp = flashReadBuffer[index++];
crcFlash = b_crc16( crcFlash, b_temp );
}
#endif
return crcFlash;
}
//#endif
uint16_t __attribute__((section("boot"))) b_getRecord()
{
// find two consecutive STX characters
char currentChar = ETX;
char previousChar = STX;
while((currentChar != STX) || (previousChar != STX) )
{
previousChar = currentChar;
currentChar = b_readUART();
}
b_CAN.bytes[0] = previousChar;
b_CAN.bytes[1] = currentChar;
b_receivePointer = 2;
while( b_receivePointer < 8 )
{
currentChar = b_readUART();
b.charBuffer[b_receivePointer++] = currentChar;
}
b_CAN.words[1] = b.wordBuffer[1];
b_CAN.words[2] = b.wordBuffer[2];
b_CAN.words[3] = b.wordBuffer[3];
b_CAN.words[4] = b.wordBuffer[4];
uint16_t length = b.charBuffer[b_receivePointer - 5]; // data length
for( i = 0; i < length; i++)
{
currentChar = b_readUART();
b.charBuffer[b_receivePointer++] = currentChar;
}
return b_receivePointer;
}
void __attribute__((section("boot"))) b_crcMessage(bool flash, bool eeProm)
{
if(flash)
{
b_writeUART('A');
b_writeUART('C');
b_writeUART('K');
}
else
{
b_writeUART('N');
b_writeUART('A');
b_writeUART('K');
}
b_writeUART(',');
if(eeProm)
{
b_writeUART('A');
b_writeUART('C');
b_writeUART('K');
}
else
{
b_writeUART('N');
b_writeUART('A');
b_writeUART('K');
}
b_writeUART('\r');
b_writeUART('\n');
}
void __attribute__((section("boot"))) b_writeUART(char ch)
{
while(U2STAbits.TRMT == 0); // Wait for transmit register empty
U2TXREG = ch; // send character
}
char __attribute__((section("boot"))) b_readUART()
{
while(U2STAbits.URXDA == 0); //&& // Wait for receive register not empty
//(pinBoot == bootFlag) ); // abort if boot flag is reset
if(pinBoot != bootFlag) b_bootend();
char chr = U2RXREG;
return chr;
}
void __attribute__((section("boot"))) b_initUART(void)
{
U2MODEbits.UARTEN = 1; // Enable UART pins
U2BRG = baudConstant; // 9600 0r 115200 Baud - w/PLL_8
U2MODEbits.PDSEL = 0; // 8 bit, no parity
U2MODEbits.STSEL = 0; // 1 stop bit
U2STAbits.UTXISEL = 0; // Interrupt when char transferred to Transmit Shift register
U2STAbits.UTXEN = 1; // Enable transmitter
U2STAbits.URXISEL = 1; // Interrupt for each char received
IEC1bits.U2RXIE = 0; // Disable receive interrupts
IEC1bits.U2TXIE = 0; // Disable transmit interrupts
}
void __attribute__((section("boot"))) b_sendCAN() // for testing output
{
// while(C1TX2CONbits.TXREQ != 0); // overwrite if not send yet
C1TX2CONbits.TXREQ = 0; // only used for diagnostic messages
C1TX2B1 = b_CAN.words[0];
C1TX2B2 = b_CAN.words[1];
C1TX2B3 = b_CAN.words[2];
C1TX2B4 = b_CAN.words[3];
C1TX2SIDbits.SID10_6 = (testSID >> 6) & 0x001F;
C1TX2SIDbits.SID5_0 = testSID & 0x003F;
C1TX2DLCbits.DLC = 8;
C1TX2SIDbits.SRR = 0; // Normal message
C1TX2CONbits.TXPRI = 0; // Lowest transmission priority
C1TX2SIDbits.TXIDE = 0; // Standard Identifier
C1TX2CONbits.TXREQ = 1; // Transmit the message
return;
}
void __attribute__((section("boot"))) b_initCAN(void) // for testing output
{
C1CTRLbits.CANCAP = 0; // Disable CAN Capture
C1CTRLbits.CANSIDL = 1; // Stop CAN in Idle mode
C1CTRLbits.ABAT = 1; // Abort any transmit operations
C1CTRLbits.CANCKS = 0; // CAN clock is 4 Fcy
C1CTRLbits.REQOP = 4; // Set configuration mode
while(C1CTRLbits.OPMODE != 4); // wait for Configuration mode
C1CFG1bits.SJW = 0; // Synchronized jump width 1 x Tq
C1CFG1bits.BRP = 0x03; // Baud rate pre-scaler - PLL_8
C1CFG2bits.WAKFIL = 0; // Filter not used for wakeup
C1CFG2bits.SEG2PH = 2; // SEG2 - 3
C1CFG2bits.SEG2PHTS = 1; // Freely programmable
C1CFG2bits.SAM = 1; // Sample 3 times
C1CFG2bits.SEG1PH = 3; // SEG1 1 - 4
C1CFG2bits.PRSEG = 1; // PROP 5
C1CTRLbits.REQOP = 0; // Change to normal mode
while(C1CTRLbits.OPMODE != 0); // wait for Normal mode
C1INTEbits.RX0IE = 0; // Disable RX 0 Interrupt
C1INTEbits.RX1IE = 0; // Disable RX 1 Interrupt
C1INTEbits.TX0IE = 0; // Disable TX 0 Interrupt
C1INTEbits.TX1IE = 0; // Disable TX 1 Interrupt
C1INTEbits.TX2IE = 0; // Disable TX 2 Interrupt
IPC6bits.C1IP = 3; // CAN Interrupt priority
IEC1bits.C1IE = 0; // Disable CAN Interrupts
C1CTRLbits.ABAT = 1; // Abort any transmit operations
// zero CAN buffer
int i;
for(i=0;i<4;i++)
{
b_bufferCANb[i] = 0x00;
b_bufferCANb[i*2] = 0x00;
b_bufferCANw[i] = 0x0000;
}
}
uint16_t __attribute__((section("boot"))) b_crc16(uint16_t crc, uint16_t data)
{
int i;
for(i = 0; i < 16; i++, data >>= 1)
{
if((( crc & 0x0001 ) ^ ( data & 0x0001 )) == 0x0001 )
{
crc = (crc >> 1) ^ b_poly;
}
else
{
crc = crc >> 1;
}
}
return crc;
}
void __attribute__((section("boot"))) b_bootend(void)
{
asm ("goto __resetPRI");
}