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

📄 ymodem.c

📁 ATmega103、ATmega128做的开发板web server源码
💻 C
字号:
/******************************************************************
* ymodem.c: Serial Interface to PC UART
* 
* Copyright (c) 2001 Atmel Corporation.
* All Rights Reserved.
*
* You are autorized to use, copy and distribute this software only at 
* a single site (the term "site" meaning a single company location). 
* This copyright notice must be included in any copy, modification 
* or portion of this software merged into another program.
* 
* This software is licenced solely for use with Atmel AVR micro 
* controller family. The software may not be modified to execute on 
* any other microcontroller architectures
*
* This software is provided "as is"; Without warranties either express
* or implied, including any warranty regarding merchantability, 
* fitness for a particular purpose or noninfringement. 
*
* In no event shall Atmel or its suppliers be liable for any special, 
* indirect,incidential or concequential damages resulting from the 
* use or inability to use this software.
*
* Revision history:
*
* January 17, 2001:   Version 1.0   Created by JB
* July 13, 2001		  Version 1.2     JB
* 					- Changed to IAR compiler V2.25
*					- Renamed flash file functions to avoid conflict with 
*					  standard file I/O names	
*					- Bug fixes in HTTP
*					- Speed optimization in TCP 
*
*
* July 13, 2001		Version 1.2
* 					- Changed to IAR compiler V2.25
*					- Renamed flash file functions to avoid conflict with 
*					  standard file I/O names	
*					- Bug fixes in HTTP
*					- Speed optimization in TCP 
*******************************************************************/
#include "iom103.h"
#include "ymodem.h"
#include "ffile.h"
#include "string.h"      
#include "stdio.h"
#include "ina90.h"


void TransmitByte( unsigned char data );
void Send (unsigned char *string);                       

char ymodemBuf[1030];
char *ymodemRecvPtr;
char ymodemRecvError;
unsigned char ymodemPacketNumber;
unsigned char ymodemSync;
unsigned char ymodemNakCnt;
unsigned int  ymodemCnt;
unsigned int  ymodemDataLength;
FFILE * ymodemDestFile;

void initYmodem(void) 
{
    unsigned char temp;
    // portd bit 2 used to start data reception 
    // Pb7, Pb6, Pb5, Pb4, Pb3, Pb2, Pb1, Pb0
    //  O    O    O    O    O    O    O    O
    //  1    1    1    1    1    1    1    1
    DDRD = 0xfb;
    PORTD = 0xff; 
    temp = UDR;     // Dummy reading, ignore compiler warning    
    UCR = 0x98;     // enable receiver, transmitter, and receiver interrupt
    UBRR = 29;      // 9.6k with 4.608Mhz crystal          
    ymodemRecvPtr = &ymodemBuf[0];
    ymodemSync = 1;
    ymodemPacketNumber=0;
    ymodemNakCnt=0;
}

 
/* uart interrupt routine*/
#pragma vector = UART_RX_vect
__interrupt void UART_RX_interrupt(void) 
{
  char *localPtr = ymodemRecvPtr;
  char filename[13];
  unsigned char packet = canc; //status flag   
  unsigned int packetSize;

    // check for errors before reading data register ... reading UDR clears status
    if (USR & 0x18)           // Framing or over run error
    {
      ymodemRecvError = true; // will NAK sender
      ymodemBuf[0]=0;
    }
    // always read a character otherwise another interrupt could get generated
    *localPtr++ = UDR;        // get char
                                              
    //determine if it is a complete pathname packet
    if(ymodemBuf[0]==SOH)
    {
        packetSize = 128;
        if ( (ymodemBuf[1] == 0) && (localPtr == (&ymodemBuf[133])) ) 
        {
          if (( ymodemBuf[2]) == 0xff)
          {                                                 // block number and block number checksum are ok
            if ((calcrc(&ymodemBuf[3],128)) == (unsigned int)((ymodemBuf[131] << 8) | (ymodemBuf[132]))) 
            {
              strncpy(filename, &ymodemBuf[3],13);          //read pathname
              if (!strlen(filename)) 
              {                                             //a null pathname terminates tranmission
                packet = good;
              }
              else if (strlen(filename)<13)
              {          
                ffclose(ymodemDestFile);                     //in case there is an open file
                ffdelete(filename);                          //delete file first
                ymodemDestFile=ffopen(filename, 'w');        //open file
                strcpy(filename, &ymodemBuf[strlen(filename)+4]);
                sscanf(filename,"%d",&ymodemDataLength);    //read data length
                if (ymodemDestFile!=NULL) 
                {                                            //file has been opened
                  packet = good;
                }
              }
            }
          }             
          localPtr = &ymodemBuf[0];
          respond(packet);                                  //send respons
        }                                                   //determine if buffer is full
        if(localPtr != (&ymodemBuf[133]))
        {
            ymodemRecvPtr = localPtr;                       // restore global pointer
            return;
        }
    }
    else if(ymodemBuf[0]==STX)                              //buffer is full, or end of transmission, or first char unknown
    {
        packetSize = 1024;
        if(localPtr != (&ymodemBuf[1029]))
        {
            ymodemRecvPtr = localPtr;                       // restore global pointer
            return;
        }    
    }
    packet = validate_packet(&ymodemBuf[0], packetSize);  //validate
      
    if (packet==good) 
    {
 	   if (ymodemPacketNumber == 1) 
       {      
         ymodemSync=0;                                     //sync is done
       }          
       if (ymodemDataLength<packetSize) 
       {
         ffwrite(ymodemDestFile, &ymodemBuf[3], ymodemDataLength);//write last packet to dataflash
       }
        else 
        { 
          ffwrite(ymodemDestFile, &ymodemBuf[3], packetSize); //write to dataflash
          ymodemDataLength-=packetSize;
        }
      }                
      if (packet==end) 
      {
        ffclose(ymodemDestFile);                             //close file
        ymodemPacketNumber=0;                              
        ymodemSync=1;
      }                                               
      if (!ymodemSync) 
      {                                                     //reset timeout counters
        ymodemCnt=0;
        ymodemNakCnt=0;
      }
      localPtr = &ymodemBuf[0];
      respond(packet);
    ymodemRecvPtr = localPtr;                               // restore global pointer
}       
                     

/* validate_packet*/
unsigned char validate_packet(char *bufptr, unsigned int size) 
{
    unsigned char packet = bad;
    unsigned char bufptr0 = bufptr[0];
    unsigned char bufptr1 = bufptr[1];
                     
    if (!ymodemRecvError) 
    {
        if (bufptr0 == SOH || (size==1024 && bufptr0 == STX)) 
        {                                                   // valid start
            if (bufptr1 == ((ymodemPacketNumber+1))) 
            {                                               // sequential block number ?
                if ((bufptr1 + bufptr[2]) == 0xff) 
                {                                           // block number and block number checksum are ok 
                                                            // compute CRC and validate it                    
                    if ((calcrc(&bufptr[3],size)) == (unsigned int)((ymodemBuf[size+3] << 8) | (ymodemBuf[size+4]))) 
                    {
                        ymodemPacketNumber++;               // good packet ... ok to increment
                        packet = good;
                    }    
                }            // block number checksum
            }           // bad block number or same block number
            else if (bufptr1 == (ymodemPacketNumber)) 
            {                                               // same block number ... ack got glitched
                packet = dup;                               // packet is previous packet don't inc packet number
            }
        }
        else if (bufptr0 == EOT)                            // check for the end   
        {
            packet = end;
        }
    }
    else
    {
        packet = err;
    }
    return (packet);      
}
                     
/*wait for sender to empy its transmit buffer*/
void purge(unsigned char temp) 
{
  unsigned char flush;
  unsigned char ii=100;
  
  while (!(USR & 0x20))         // wait till Data register is empty
  {
  }
  
  do 
  {
    flush = UDR;                // Dummy reading, ignore compiler warning
  } while (--ii);
  UDR = temp;
}      

void respond(char packet) 
{
    if (ymodemRecvError)
    {
      ymodemRecvError = false;  // framing and over run detection
    }
    if ((packet == good) || (packet == dup) || (packet == end)) 
    {
        while (!(USR & 0x20));  // wait till transmit register is empty
        UDR = ACK;              // now for the next packet
    } 
    else if (packet == canc) 
    {
        purge(CAN);             // tell sender to cancel
        UDR = CAN;              // must be done twice
    }
    else 
    {
        purge(NAK);             // let transmitter empty its buffer  
                                // tell sender error
    }
}                                             

void checkYmodem(void) 
{
  ymodemCnt++;           
  
  if (ymodemCnt>YMODEM_3SEC) 
  {
    ymodemCnt = 0;
    
    if (ymodemSync) 
    { 
      while (!(USR & 0x20));    // wait till Data register is empty
      UDR = CRCCHR;             // send a 'C'
    }
    else 
    {
      ymodemRecvPtr=&ymodemBuf[0]; //resett buffer pointer
      if (ymodemNakCnt > 3) 
      {
        purge(CAN);             // tell sender to cancel
        UDR = CAN;              // must be done twice
        ymodemPacketNumber=0;
        ymodemSync=1;
        ymodemNakCnt=0;   
        ffclose(ymodemDestFile);
      }
      else 
      {
        purge(NAK);             // send NAK
        ymodemNakCnt++;
      }
    }
  }
}

unsigned int calcrc(char *ptr, int count) 
{
    unsigned int crc = 0;
    unsigned char i;

    while(--count >= 0)
    {
      crc = crc ^ (unsigned int) *ptr++ << 8;
      for(i=0; i<8; ++i)
      {
        if (crc & 0x8000)
        {
          crc = crc << 1 ^ 0x1021;
        }
        else
        {
          crc = crc << 1;
        }
      }
    } 
        
    return (crc);
}

⌨️ 快捷键说明

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