xmodem.c

来自「使用JTAG口对AT91R40008芯片进行FLASH编程的程序」· C语言 代码 · 共 485 行 · 第 1/2 页

C
485
字号
//*----------------------------------------------------------------------------
//*      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'
//* 1.1 05/01/11        : Com light modification
//*----------------------------------------------------------------------------


//* ------------------------------ include file -------------------------------
#include "xmodem.h"
#include    "drivers/com/com.h"  //* Communication driver

//* ----------------------------  extern function  ----------------------------

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

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

static XmodemFrame  input_buff[1];

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 char buffer_send[XMODEM_DATA_SIZE];

//* -------------------------------  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 = 0x85 ; //sizeof(input_buff);
}
//*----------------------------------------------------------------------------
//* Function Name       : get_usart
//* Object              : Get char in usart
//* Input Parameters    : none
//* Output Parameters   : none
//*----------------------------------------------------------------------------
static void get_usart (void)
{
    // check for recv_errors before reading data register
    // Framing, over run or parity error

    if ( at91_usart_get_status(Xmodem_COM->usart) & (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)
        {
            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 == 0 )
        {
            init_usart();
            buffer_status = FULL;

        }
    }
}

//*----------------------------------------------------------------------------
//* 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_3S;
    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 status)
{
    if (status)
    {
        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

⌨️ 快捷键说明

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