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

📄 xmodem.c

📁 ARM入门的好帮手.包含了从简单到相对较复杂的程序.
💻 C
字号:
//*----------------------------------------------------------------------------
//*      ATMEL Microcontroller Software Support  -  ROUSSET  -
//*----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*----------------------------------------------------------------------------
//* File Name           : xmodem.c
//* Object              : xmodem receive utility with PDC
//*
//* 1.0 14/11/00 JPP    : Creation
//* without PDC 256K    AT->PC      PC->RAM
//*   38400              1'26 s       1'52
//*  115200              0'56 s       1'
//*----------------------------------------------------------------------------


//* ------------------------------ include file -------------------------------
#include "xmodem.h"

#include "drivers/com/com.h"                    //* Communication driver

//* --------------------------- Constant definition ---------------------------

 #define WAIT_1S    100000
 #define WAIT_2S    (WAIT_1S*2)
 #define WAIT_3S    (WAIT_1S*3)
//* ----------------------------  extern function  ----------------------------

//* ---------------------------  extern global data  --------------------------
extern ComDesc *Xmodem_COM;

//* -----------------------------  Local variable -----------------------------
static int wait_time;


static volatile u_char buffer_status;
static volatile u_char recv_error;
static volatile u_char timed_out;
static u_char packet_number;
static volatile u_char eot_flag;
static u_char next_frame=TRUE;


static XmodemFrame *ptr_frame;
static XmodemFrame  input_buff[2];

//* -------------------------------  Functions  -------------------------------
//*----------------------------------------------------------------------------
//* Function Name       : time_out
//* Object              : Compute the CRC
//* Input Parameters    : Global  wait_time
//* Output Parameters   : Global  timed_out = TRUE
//*----------------------------------------------------------------------------
static void time_out(void)
{
   wait_time--;
   if (wait_time <=0)
   {
        wait_time=0;
        timed_out= TRUE;
    }
}

//*----------------------------------------------------------------------------
//* Function Name       : init_usart
//* Object              : init_usart_with PDC
//* Input Parameters    : Global  time_out
//* Output Parameters   : Global  timed_out = TRUE
//*----------------------------------------------------------------------------
static void init_usart(void)
{

    //* Store the address of the buffer
    Xmodem_COM->usart->usart_base->US_RPR = (u_int) input_buff ;

    //* Store the number of bytes to receive
    Xmodem_COM->usart->usart_base->US_RCR = sizeof(input_buff);
}
//*----------------------------------------------------------------------------
//* Function Name       : get_usart
//* Object              : Get char in usart
//* Input Parameters    : none
//* Output Parameters   : none
//*----------------------------------------------------------------------------
static void get_usart (void)
{
    u_int status;

    // check for recv_errors before reading data register
    // Framing, over run or parity error
    status = at91_usart_get_status(Xmodem_COM->usart);
    if ( status & (US_OVRE | US_FRAME| US_PARE) )
    {
        recv_error = TRUE;
        //* Reset Status Bits
        at91_usart_trig_cmd( Xmodem_COM->usart,US_RSTSTA);
    }
    else
    {
        //* check end of transmission
        if ( (input_buff[0].Header != SOH) | (input_buff[1].Header != SOH))
        {
            buffer_status = FULL;
            eot_flag = TRUE;
        }
        //* check end of frame
        //* if the recivied size at XMODEM_FRAME_SIZE the [0] is full
        else if( ( Xmodem_COM->usart->usart_base->US_RCR == XMODEM_FRAME_SIZE) &
          (next_frame==TRUE)
        )

        {
            buffer_status = FULL;
            ptr_frame= &input_buff[0];
        next_frame=FALSE;
        }
        else if ( Xmodem_COM->usart->usart_base->US_RCR == 0 )
        {
            init_usart();
            buffer_status = FULL;
            ptr_frame= &input_buff[1];
        next_frame=TRUE;
        }
    }
}

//*----------------------------------------------------------------------------
//* Function Name       : calcrc
//* Object              : Compute the CRC
//* Input Parameters    : <ptr>  char pointer
//*                       <count> nb of char
//* Output Parameters   : crc value
//*----------------------------------------------------------------------------
static u_short calcrc(u_char *ptr, int count)
{

    u_short crc, cmpt;

    crc = 0;
    //* For  all char
    while (--count >= 0)
    {

        crc = crc ^ (int) *ptr++ << 8;
        //* For All bit
        for (cmpt = 0; cmpt < 8; cmpt++)
        {
            if (crc & 0x8000)
                crc = crc << 1 ^ CRC16POLY;
            else
                crc = crc << 1;
        }//* end bit
    }//* Frame end

    return (crc & 0xFFFF);
}

//*----------------------------------------------------------------------------
//* Function Name       : recv_wait_frame
//* Object              : wait data or time out
//* Input Parameters    : <time> Wait time
//* Output Parameters   : none
//*----------------------------------------------------------------------------
static void recv_wait_frame(int time)
{

    buffer_status = EMPTY;
    timed_out = FALSE; // set in timer counter 0 overflow interrupt routine
    recv_error = FALSE; // framing and over run detection
    wait_time = time;
    // wait for packet or error
    while (!buffer_status && !recv_error && !timed_out)
    {
        get_usart();
        time_out();
    }

}
//*----------------------------------------------------------------------------
//* Function Name       : purge
//* Object              : wait 1 second for sender to EMPTY its transmit buffer
//* Input Parameters    : none
//* Output Parameters   : none
//*----------------------------------------------------------------------------
static void purge(void)
{
    wait_time =WAIT_1S;
    init_usart();
    while (!timed_out) // read uart until done
    {
        time_out();
    }
    //* stop pdc reception
    Xmodem_COM->usart->usart_base->US_RCR = 0;
    //* clear error
    at91_usart_trig_cmd( Xmodem_COM->usart,US_RSTSTA);
}

//*----------------------------------------------------------------------------
//* Function Name       : respond
//* Object              : Compute the CRC
//* Input Parameters    : <responce type>: TRUE send ACK FALSE send NAK
//* Output Parameters   : none
//*----------------------------------------------------------------------------
static void respond(u_char packet)
{
    if (packet)
    {
        at91_send_byte(Xmodem_COM,ACK);
    }
    else
    { // tell sender error
        at91_send_byte(Xmodem_COM,NAK);
    }
}

//*----------------------------------------------------------------------------
//* Function Name       : validate_packet
//* Object              : check the data frame
//*          SOH | nr | ns | < 128 data > | check|sum |
//*     data size = XMODEM_FRAME_SIZE 133
//* Input Parameters    : <check_buf> end address buffer address
//* Output Parameters   : none
//*----------------------------------------------------------------------------
static u_char validate_packet(XmodemFrame *check_buf)
{

u_short crc;
u_char status = NOK;

    if (buffer_status && !recv_error)
    { // no framing, over run, or time out errors

        if (check_buf->Header == SOH)
        { // valid start

            if (check_buf->packet == ((packet_number+1) & 0xff))
            { // sequential block number ?

                if ((check_buf->packet + check_buf->packet_crc) == 0xff)
                { // block number and block number checksum are ok

                    // compute CRC and validate it
                    crc = calcrc((u_char*)check_buf->data,XMODEM_DATA_SIZE);
                    if ( (check_buf->crc_lsb == (unsigned char)(crc >> 8)) &&
                         (check_buf->crc_msb == (unsigned char)(crc))
                       )

                    {
                        packet_number++;
                        status = OK;
                    }// if end CRC

                }// block Checksum
            }// sequential block
        }// valid start
        // check for the end
        else if (check_buf->Header == EOT)
        {// no start
            eot_flag = TRUE;
            status = OK;
        }
    }// recieved with error
    return (status);
}

//*----------------------------------------------------------------------------
//* Function Name       : xmodem_receive
//* Object              : Recived all frame
//* Input Parameters    : address of write function (flash,or ram, ...
//* Output Parameters   : Status
//* Functions called    : validate_packet       static function
//*                       respond               static function
//*----------------------------------------------------------------------------
int xmodem_receive(int (*write_function)(u_char *ptr_data,int size))
{

u_char packet;
	int status;
    // init static data
    packet_number = 0x00;
    eot_flag = FALSE;
    ptr_frame = input_buff;
    buffer_status = EMPTY;
    next_frame=TRUE;
    //* init the header
    input_buff[1].Header=input_buff[0].Header=SOH;
    init_usart();
	status = TRUE;
    // send 'C' character until we get a packet from the sender
    while (!buffer_status)
    {
        at91_send_byte(Xmodem_COM,CRCCHR);
        recv_wait_frame(WAIT_1S/2);

    }

    //* validate 1st packet
    packet = validate_packet(ptr_frame);
    //* ack or nak
    respond(packet);
    if ( packet)
    { // if Ok write data
        //* external function for write data
       if (!(*write_function)((u_char *) ptr_frame->data,XMODEM_DATA_SIZE))
       {
		   eot_flag = TRUE ;
		   status = FALSE;
	   }
    }


    // get remainder of file
    while (!eot_flag)
    {
        // wait for error or buffer FULL
        recv_wait_frame(WAIT_2S);
        // validate the packet
        packet = validate_packet(ptr_frame);
        // ack or nak
        respond(packet);
        if (packet && (eot_flag == FALSE))
        { // if Ok write data
       		if (!(*write_function)((u_char *) ptr_frame->data,XMODEM_DATA_SIZE))
       		{
				eot_flag = TRUE ;
				status = FALSE;
	   		}
        }

    } // end of 1st file transmission
    at91_send_byte(Xmodem_COM,ACK);
    purge();
    return  (status);
}

//*----------------------------------------------------------------------------
//* Function Name       : recv_char_wait
//* Object              : wait data
//* Input Parameters    : <data> char to read
//* Output Parameters   : if Recievied char retrun this char
//*----------------------------------------------------------------------------
static u_char recv_char_wait(u_char data)
{
    int  read;
    buffer_status    = EMPTY;
    recv_error       = FALSE; // framing and over run detection

    timed_out = FALSE; // set in timer counter 0 overflow interrupt routine
    wait_time = WAIT_3S;

    // wait for packet or error
    while (!buffer_status && !recv_error && !timed_out)
    {
        if ( at91_usart_get_status(Xmodem_COM->usart) & (US_OVRE | US_PARE) )
        {
            recv_error = TRUE;
            //* Reset Status Bits
            at91_usart_trig_cmd( Xmodem_COM->usart,US_RSTSTA);
        }
        else if (!at91_getch(Xmodem_COM,&read))
        {
            // determine if read char is ok buffer FULL
            if ((u_char)read == data )
                    buffer_status = FULL;
        }
        // Time out
        time_out();
    }
    return( (u_char) read);
}

//*----------------------------------------------------------------------------
//* Function Name       : xmodem_transmit
//* Object              : transmit data area
//* Input Parameters    : <bufptr> start data address
//*                       <size>   lenght
//* Output Parameters   : none
//* Functions called    : at91_send_byte        define in com.c driver
//*                       at91_print_frame      define in com.c driver
//*                       calcrc                static function
//*----------------------------------------------------------------------------
int xmodem_transmit(u_char *bufptr,u_int len)
{
u_int   count;
int status = TRUE;
u_short crc;
u_char sent_packet = 0x01;
    //* wait the recievied
    while ( recv_char_wait(CRCCHR) != CRCCHR );

    for (count =0 ; count <len ;sent_packet++)
    {
        // send header
        at91_send_byte(Xmodem_COM,SOH);
        at91_send_byte(Xmodem_COM,sent_packet);
        at91_send_byte(Xmodem_COM,0xFF - sent_packet);
        // send data frame
        at91_print_frame (Xmodem_COM, (char*) bufptr , XMODEM_DATA_SIZE);
        count+= XMODEM_DATA_SIZE;
        bufptr+=XMODEM_DATA_SIZE;

        // send CRC
        crc = calcrc((bufptr-XMODEM_DATA_SIZE),XMODEM_DATA_SIZE);
        at91_send_byte(Xmodem_COM,(u_char)(crc >> 8));
        at91_send_byte(Xmodem_COM,(u_char)(crc));
        // wait ACK
        switch ( recv_char_wait(ACK))
        {
            case NAK: //* retransmit the la st frame
                bufptr -=XMODEM_DATA_SIZE;
                count -=XMODEM_DATA_SIZE;
                sent_packet--;
                status =FALSE;
            break;
            case ACK://* Continue
            break;
            default: // Stop the transmission
                at91_send_byte(Xmodem_COM,NAK);
                count = len;
            break;
        }// switch End
    }// for end
    // send end of file
    at91_send_byte(Xmodem_COM,EOT);
    return (status);
}

⌨️ 快捷键说明

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