⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bootloader_smbus.c

📁 用AVR453开发的电池保护板的C语言程序,希望对大家有用!
💻 C
📖 第 1 页 / 共 3 页
字号:

void EEwrite(unsigned int address, unsigned char data)
{
  while(EECR & (1<<EEPE));
  EEAR = address;
  EEDR = data;
  EECR = (1<<EEMPE);                    //do an Erase and a Write
  EECR = (1<<EEMPE) | (1<<EEPE);
}






void LoopMemory(void)
{
  if(LoopFlag == 'E')		//this indicates "Write to EEPROM"
  {
    if(EEbusy())
      return;
    EEwrite(eptr++, SRAMbuffer[dest_i++]);
    if(--ctr)
      return;
    Status = SUCCESS;
    LoopFlag = 0;
    return;
  }
  else
  if(LoopFlag == 'e')		//this indicates "Erase EEPROM"
  {
    if(EEbusy())
      return;
    EEerase(eptr++);
    if(--ctr)
      return;
    Status = SUCCESS;
    LoopFlag = 0;
    return;
  }
}





//This function interprets received commands.
void SMB_CmdInterpreter(void)
{
  unsigned char temp;

  if(UsePEC)				//check the CRC of the received packet.
  {
    temp = 0;				//use this as our CRC value.

    do { temp = FastCRC(temp, TW_RxBuf[TW_RxBufIndex++]); }
    while(TW_RxBufCnt != TW_RxBufIndex);

    if(temp)	//The result of a CRC check SHOULD be =0 if all was ok.
    {
      Status = CRCERROR;
      TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);	//have TWI continue from where it stalled.
      return;
    }
  }
  // Message is valid enough to warrant calling each command's handler now.
  Status = BUSY;                        //in case it's a "looped" operation...


  if(!BigData)
  {
  //  TW_RxBufIndex = 3;			//point to the first byte of Received Data.
    lomemptr = TW_RxBuf[TWRX_LOADDR];
    himemptr = TW_RxBuf[TWRX_HIADDR];
    src_i = TWRX_DATA;
    dest_i = TW_RxBuf[TWRX_OFFSET];
    ctr = TW_RxBuf[TWRX_SIZE];

    temp = TW_RxBuf[TWRX_CMD];          //What is the command?
  }
  else
  {
    temp = 'I';
    src_i = 3;				//for all follow-on blocks, data MUST start at 3!
    //Note that ctr and dest_i are still valid from the previous block.
  }


  if(temp == 'W')                     //Write SRAMbuffer data into memory
  {
    if(TW_RxBuf[TWRX_MEM] == 'F')     //flash?
    {
      src_i = 0;                      //index into SRAMbuffer
      lomemptr &= 0x80;               //make sure the page boundary is clean
      dest_i = lomemptr;
      do
      {
        #pragma diag_suppress=Pe1053  // Suppress warning for conversion from long-type address to flash ptr.
        _FILL_TEMP_WORD(((himemptr<<8)|dest_i), (SRAMbuffer[src_i]|(SRAMbuffer[src_i+1]<<8)));
        #pragma diag_default=Pe1053   // Back to default.
        src_i += 2;                   // Select next word from SRAMbuffer.
        dest_i += 2;                  // Update flash page pointer.
      }
      while(src_i < 0x80);          // Loop until all bytes written.

      _PAGE_WRITE((himemptr<<8)|lomemptr);
      _WAIT_FOR_SPM();
      _ENABLE_RWW_SECTION();

      Status = SUCCESS;
    }
    else
    if(TW_RxBuf[TWRX_MEM] == 'E')  //eeprom?
    {
      eptr = (himemptr<<8) | lomemptr;
      if((eptr + ctr) > 512)
        Status = BADPARAM;
      else
      {
        LoopFlag = 'E';		//this indicates "Write to EEPROM"
      }
    }
    else
      Status = BADPARAM;
  }

  else
  if(temp == 'V')       //Verify info in SRAMbuffer against memory
  {
    if(TW_RxBuf[TWRX_MEM] == 'F')  //flash?
    {
      src_i = SUCCESS;              //use this variable to hold status
      dest_i = 0;
      fptr = (unsigned char __flash *)(lomemptr | (himemptr<<8));
      do { if(SRAMbuffer[dest_i++] != *fptr++) src_i=FAILURE; }
      while (dest_i < 128);
      Status = src_i;
    }
    else
    if(TW_RxBuf[TWRX_MEM] == 'E')  //eeprom?
    {
      eptr = (himemptr<<8) | lomemptr;
      if((eptr + ctr) > 512)
        Status = BADPARAM;
      else
      {
        src_i = SUCCESS;            //use this variable to hold status
        do { if(SRAMbuffer[dest_i++] != EEget(eptr++)) src_i=FAILURE; }
        while (--ctr);
        Status = src_i;
      }
    }
    else
      Status = BADPARAM;
  }

  else
  if(temp == 'E')       //Erase memory, starting at the specified address
  {
    if(TW_RxBuf[TWRX_MEM] == 'F')  //flash?
    {
      _WAIT_FOR_SPM();
      #pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
      _PAGE_ERASE( (himemptr<<8) | (lomemptr & 0x80) );
      #pragma diag_default=Pe1053 // Back to default.

      Status = SUCCESS;
    }
    else
    if(TW_RxBuf[TWRX_MEM] == 'E')  //eeprom?
    {
      eptr = (himemptr<<8) | lomemptr;
      if((eptr + ctr) > 512)
        Status = BADPARAM;
      else
      {
        LoopFlag = 'e';		//this indicates "erase EEPROM"
      }
    }
    else
      Status = BADPARAM;
  }

  else
  if(temp == 'P')       //prepare to Patch a block of memory by reading it into SRAMbuffer
  {
    if(TW_RxBuf[TWRX_MEM] == 'F')  //flash?
    {
      if(lomemptr & 0x7F)          //it must be on a page boundary!!
        Status = BADPARAM;
      else
      {
        dest_i = 0;
        fptr = (unsigned char __flash *)(lomemptr | (himemptr<<8));
        do {SRAMbuffer[dest_i++] = *fptr++; }
        while (dest_i < 128);
        Status = SUCCESS;
      }
    }
    else
    if(TW_RxBuf[TWRX_MEM] == 'E')  //eeprom?
    {
      eptr = (himemptr<<8) | lomemptr;
      if((eptr + ctr) > 512)
        Status = BADPARAM;
      else
      {
        do { SRAMbuffer[dest_i++] = EEget(eptr++); }
        while (--ctr);
        Status = SUCCESS;
      }
    }
    else
      Status = BADPARAM;
  }

  else
  if(temp == 'A')       //Activate BootLoader ISP code (ignored in this code)
  {
    Status = SUCCESS;   //no action required, just ignore
  }

  else
  if(temp == 'I')       //Insert data from this packet into SRAMbuffer at the offset specified
  {
    if((ctr+dest_i) > 128)
      Status = BADPARAM;
    else
    {
      if(!BigData)
      {
      	if(ctr > 26)	//26 is the most that can fit in an initial packet
      	{
      	  BigData = 1;
          temp = TW_RxBuf[TWRX_BLKCNT] - 6;
      	}
      	else
      	  temp = ctr;
      }
      else              //this is a chained packet and MAY contain up to 32 bytes of data.
      {
        if(ctr <= TW_RxBuf[TWRX_BLKCNT])
          BigData = 0;
        temp = TW_RxBuf[TWRX_BLKCNT];
      }


      do
      {
      	SRAMbuffer[dest_i++] = TW_RxBuf[src_i++];
      	ctr--;
      }
      while (--temp);
      Status = SUCCESS;
    }
  }

  else
  if(temp == 'w')	//first decrypt the entire SRAM block, THEN write.
  {
    ;	//! \todo  Add code here if encryption is desired.
  }

  else
  if(temp == 'v')	//first decrypt the entire SRAM block, THEN verify.
  {
    ;	//! \todo  Add code here if encryption is desired.
  }

  else
  if(temp == 'X')       //Exit the BootLoader
  {
    asm("jmp 0");
  }

  else	//Not a valid command from our list
  {
    SMB_BusTimeout();	//Generate a bus timeout.
    TW_RxBufIndex = 0;	//Wipe out anything in the buffer, just in case.
    TW_RxBufCnt = 0;			
    return;
  }
  //At this point it looks like everything went OK.
  TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);	//have TWI continue from where it stalled.
  return;
}





//This function restores the SMBus & the TWI_ISR state machine to normal after
//  we have deliberately generated a bus timeout error (in order to tell the
//  Master that something was wrong with his last command).
void SMB_RestoreBus(void)
{
  TWCR = 0;			//shut down the peripheral
  TW_state = TW_IDLE;	//force an init of the state machine
  TWAR = 0x16;
  TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);	// | (1<<TWSTO)  re-enable

  //Note that we must be careful not to generate some kind of bus error
  // as a result of waking back up, or we will get into an endless loop
  // by generating another bus timeout if the IDLE state doesn't like
  // something it sees when it comes back to life.
}







/* *************************************************************************
 *
 *   Utilities for SMBus commmunications
 *
 ************************************************************************* */



__flash unsigned char crctable[16] =  {0,0x07,0x0E,0x90, 0x1c,0x1b,0x12,0x15, 0x38,0x3F,0x36,0x31, 0x24,0x23,0x2A,0x2D};
__flash unsigned char crctable2[16] = {0,0x70,0xE0,0x90, 0xC1,0xB1,0x21,0x51, 0x83,0xF3,0x63,0x13, 0x42,0x32,0xA2,0xD2};

unsigned char FastCRC(unsigned char LastCRC, unsigned char newbyte)
{
  unsigned char index;

  index = newbyte;
  index ^= LastCRC;
  index >>= 4;
  LastCRC &= 0x0F;
  LastCRC ^= crctable2[index];

  index = LastCRC;
  index ^= newbyte;
  index &= 0x0F;
  LastCRC &= 0xF0;
  LastCRC ^= crctable[index];

  return(LastCRC);
}

/*  This version doesn't require crctable2[], but requires more shifts.
unsigned char SlowerCRC(unsigned char LastCRC, unsigned char newbyte)
{
  unsigned char index;

  index = newbyte;
  index ^= LastCRC;
  index >>= 4;
  LastCRC <<= 4;
  LastCRC ^= crctable[index];

  index = LastCRC >> 4;
  index ^= newbyte;
  index &= 0x0F;
  LastCRC <<= 4;
  LastCRC ^= crctable[index];

  return(LastCRC);
} */














⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -