ymodem send file

/*******************************************************************************
** 文件名: ymodem.c
** 版本:   1.0
** 工作环境: RealView MDK-ARM 4.14
** 生成日期: 2011-04-29
** 功能: 和Ymodem.c的相关的协议文件
                负责从超级终端接收数据(使用Ymodem协议),并将数据加载到内部RAM中。
                如果接收数据正常,则将数据编程到Flash中;如果发生错误,则提示出错。
** 相关文件: stm32f10x.h
** 修改日志: 2011-04-29   创建文档
*******************************************************************************/


/* 包含头文件 *****************************************************************/
#if 1


#include "ymodem.h"
#include "stm32f10x.h"
#include "stm32f10x_conf.h"
#include "ff.h" /* FatFs configurations and declarations */
#include "diskio.h" /* Declarations of low level disk I/O functions */




#include "usart.h"
#include
#include




#define ApplicationAddress 0
 #define PAGE_SIZE                         (0x400)    /* 1 Kbyte */
 #define FLASH_SIZE                        (0x20000)  /* 128 KBytes */
//计算上传文件大小 
#define FLASH_IMAGE_SIZE                   (u32) (FLASH_SIZE - (ApplicationAddress - 0x08000000))
 


#define IS_AF(c)  ((c >= 'A') && (c <= 'F'))
#define IS_af(c)  ((c >= 'a') && (c <= 'f'))
#define IS_09(c)  ((c >= '0') && (c <= '9'))
#define ISVALIDHEX(c)  IS_AF(c) || IS_af(c) || IS_09(c)
#define ISVALIDDEC(c)  IS_09(c)
#define CONVERTDEC(c)  (c - '0')


#define CONVERTHEX_alpha(c)  (IS_AF(c) ? (c - 'A'+10) : (c - 'a'+10))
#define CONVERTHEX(c)   (IS_09(c) ? (c - '0') : CONVERTHEX_alpha(c))


#define SerialPutString(x) Serial_PutString((u8*)(x))


















/* 变量声明 -----------------------------------------------------------------*/
u8 file_name[FILE_NAME_LENGTH];


u8 file_type[FILE_TYPE];


//用户程序Flash偏移
u32 FlashDestination = ApplicationAddress;
u16 PageSize = PAGE_SIZE;
u32 EraseCounter = 0x0;
u32 NbrOfPage = 0;
FLASH_Status FLASHStatus = FLASH_COMPLETE;
u32 RamSource;
u8 tab_1024[1024];




static u8 packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD];
static u8 file_size[FILE_SIZE_LENGTH];
FIL bmpfsrc;








extern UINT br,bw;


void Int2Str(u8* str, s32 intnum)
{
    u32 i, Div = 1000000000, j = 0, Status = 0;


    for (i = 0; i < 10; i++)
    {
        str[j++] = (intnum / Div) + 48;


        intnum = intnum % Div;
        Div /= 10;
        if ((str[j-1] == '0') & (Status == 0))
        {
            j = 0;
        }
        else
        {
            Status++;
        }
    }
}




uint32_t Str2Int(u8 *inputstr, s32 *intnum)
{
    u32 i = 0, res = 0;
    u32 val = 0;


    if (inputstr[0] == '0' && (inputstr[1] == 'x' || inputstr[1] == 'X'))
    {
        if (inputstr[2] == '\0')
        {
            return 0;
        }
        for (i = 2; i < 11; i++)
        {
            if (inputstr[i] == '\0')
            {
                *intnum = val;
                //返回1
                res = 1;
                break;
            }
            if (ISVALIDHEX(inputstr[i]))
            {
                val = (val << 4) + CONVERTHEX(inputstr[i]);
            }
            else
            {
                //无效输入返回0
                res = 0;
                break;
            }
        }


        if (i >= 11)
        {
            res = 0;
        }
    }
    else//最多10为2输入
    {
        for (i = 0; i < 11; i++)
        {
            if (inputstr[i] == '\0')
            {
                *intnum = val;
                //返回1
                res = 1;
                break;
            }
            else if ((inputstr[i] == 'k' || inputstr[i] == 'K') && (i > 0))
            {
                val = val << 10;
                *intnum = val;
                res = 1;
                break;
            }
            else if ((inputstr[i] == 'm' || inputstr[i] == 'M') && (i > 0))
            {
                val = val << 20;
                *intnum = val;
                res = 1;
                break;
            }
            else if (ISVALIDDEC(inputstr[i]))
            {
                val = val * 10 + CONVERTDEC(inputstr[i]);
            }
            else
            {
                //无效输入返回0
                res = 0;
                break;
            }
        }
        //超过10位无效,返回0
        if (i >= 11)
        {
            res = 0;
        }
    }


    return res;
}




u32 FLASH_PagesMask(__IO u32 Size)
{
    u32 pagenumber = 0x0;
    u32 size = Size;


    if ((size % PAGE_SIZE) != 0)
    {
        pagenumber = (size / PAGE_SIZE) + 1;
    }
    else
    {
        pagenumber = size / PAGE_SIZE;
    }
    return pagenumber;


}




void Serial_PutString(u8 *s)
{
    while (*s != '\0')
    {
        SerialPutChar(*s);
        s++;
    }
}


u32 SerialKeyPressed(uint8_t *key)
{


    if ( USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
    {
        *key = (u8)USART1->DR;
        return 1;
    }
    else
    {
        return 0;
    }
}






u8 GetKey(void)
{
    u8 key = 0;


    //等待按键按下
    while (1)
    {
        if (SerialKeyPressed( (u8*)&key) )
break;
    }
    return key;


}






/*******************************************************************************
  * @函数名称 Receive_Byte
  * @函数说明   从发送端接收一个字节
  * @输入参数   c: 接收字符
                timeout: 超时时间
  * @输出参数   无
  * @返回参数   接收的结果
                0:成功接收
                1:时间超时
*******************************************************************************/
static  s32 Receive_Byte (u8 *c, u32 timeout)
{
    while (timeout-- > 0)
    {
        if (SerialKeyPressed(c) == 1)
        {
            return 0;
        }
    }
    return -1;
}


/*******************************************************************************
  * @函数名称 Send_Byte
  * @函数说明   发送一个字符
  * @输入参数   c: 发送的字符
  * @输出参数   无
  * @返回参数   发送的结果
                0:成功发送
*******************************************************************************/
static u32 Send_Byte (u8 c)
{
    SerialPutChar(c);
    return 0;
}


/*******************************************************************************
  * @函数名称 Receive_Packet
  * @函数说明   从发送端接收一个数据包
  * @输入参数   data :数据指针
                length:长度
                timeout :超时时间
  * @输出参数   无
  * @返回参数   接收的结果
                0: 正常返回
                -1: 超时或者数据包错误
                1: 用户取消
*******************************************************************************/
static s32 Receive_Packet (u8 *data, s32 *length, u32 timeout)
{
    u16 i, packet_size;
    u8 c;
    *length = 0;
    if (Receive_Byte(&c, timeout) != 0)
    {
        return -1;
    }
    switch (c)
    {
    case SOH:
        packet_size = PACKET_SIZE;
        break;
    case STX:
        packet_size = PACKET_1K_SIZE;
        break;
    case EOT:
        return 0;
    case CA:
        if ((Receive_Byte(&c, timeout) == 0) && (c == CA))
        {
            *length = -1;
            return 0;
        }
        else
        {
            return -1;
        }
    case ABORT1:
    case ABORT2:
        return 1;
    default:
        return -1;
    }
    *data = c;
    for (i = 1; i < (packet_size + PACKET_OVERHEAD); i ++)
    {
        if (Receive_Byte(data + i, timeout) != 0)
        {
            return -1;
        }
    }
    if (data[PACKET_SEQNO_INDEX] != ((data[PACKET_SEQNO_COMP_INDEX] ^ 0xff) & 0xff))
    {
        return -1;
    }
    *length = packet_size;
    return 0;
}


/*******************************************************************************
  * @函数名称 Ymodem_Receive
  * @函数说明   通过 ymodem协议接收一个文件
  * @输入参数   buf: 首地址指针
  * @输出参数   无
  * @返回参数   文件长度
*******************************************************************************/




s32 Ymodem_Receive (u8 *buf)
{
//u8 packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], 
u8 *file_ptr, *buf_ptr;
s32 i, j, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;
FRESULT result;



    //初始化Flash地址变量
    FlashDestination = ApplicationAddress;


    for (session_done = 0, errors = 0, session_begin = 0; ;)
    {
        for (packets_received = 0, file_done = 0, buf_ptr = buf; ;)
        {
            switch (Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT))
            {
            case 0:errors = 0;
                
                switch (packet_length)
                {
                    //发送端终止
                case - 1:
                    Send_Byte(ACK);
                    return 0;
                    //结束传输
                case 0:
Send_Byte(ACK);
file_done = 1;
size=2;
///f_lseek(&bmpfsrc,f_size(&bmpfsrc));
f_close(&bmpfsrc );


                    break;
                    //正常的数据包
                default:
if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff))
{
Send_Byte(NAK);
}
else
{
   if (packets_received == 0)
   {
       //文件名数据包
       if (packet_data[PACKET_HEADER] != 0)
       {
           //文件名数据包有效数据区域
for (i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH);)
{
file_name[i++] = *file_ptr++;
}
            file_name[i++] = '\0';
result = f_open(&bmpfsrc, file_name, FA_OPEN_ALWAYS | FA_WRITE);  
///f_lseek(&bmpfsrc,f_size(&bmpfsrc));
//f_close(&bmpfsrc);
f_sync(&bmpfsrc);
        Send_Byte(ACK);
        Send_Byte(CRC16);
       }
       //文件名数据包空,结束传输
else
{
Send_Byte(ACK);
file_done = 1;
session_done = 1;
break;
}
   }
   //数据包
   else
   {
memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length);
if(packet_length>512){
result=f_write(&bmpfsrc,buf_ptr,512,&br);
result=f_lseek(&bmpfsrc,f_size(&bmpfsrc));
result=f_write(&bmpfsrc,buf_ptr+512,packet_length-512,&br);
result=f_lseek(&bmpfsrc,f_size(&bmpfsrc));
}
else{
result=f_write(&bmpfsrc,buf_ptr,packet_length,&br);
result=f_lseek(&bmpfsrc,f_size(&bmpfsrc));
}
///f_close(&bmpfsrc );
f_sync(&bmpfsrc);
Send_Byte(ACK);
   }
   packets_received ++;
   session_begin = 1;
}
                }
                break;
            case 1:
                Send_Byte(CA);
                Send_Byte(CA);
                return -3;
            default:
                if (session_begin > 0)
                {
                    errors ++;
                }
                if (errors > MAX_ERRORS)
                {
                    Send_Byte(CA);
                    Send_Byte(CA);
                    return 0;
                }
                Send_Byte(CRC16);
                break;
            }
            if (file_done != 0)
            {
                break;
            }
        }
        if (session_done != 0)
        {
            break;
        }
    }
    return (s32)size;
}


/*******************************************************************************
  * @函数名称 Ymodem_CheckResponse
  * @函数说明   通过 ymodem协议检测响应
  * @输入参数   c
  * @输出参数   无
  * @返回参数   0
*******************************************************************************/
s32 Ymodem_CheckResponse(u8 c)
{
    return 0;
}


/*******************************************************************************
  * @函数名称 Ymodem_PrepareIntialPacket
  * @函数说明   准备第一个数据包
  * @输入参数   data:数据包
                fileName :文件名
                length :长度
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
void Ymodem_PrepareIntialPacket(u8 *data, const u8* fileName, u32 *length)
{
    u16 i, j;
    u8 file_ptr[10];


    //制作头3个数据包
    data[0] = SOH;
    data[1] = 0x00;
    data[2] = 0xff;
    //文件名数据包有效数据
    for (i = 0; (fileName[i] != '\0') && (i < FILE_NAME_LENGTH); i++)
    {
        data[i + PACKET_HEADER] = fileName[i];
    }


    data[i + PACKET_HEADER] = 0x00;


    Int2Str (file_ptr, *length);
    for (j =0, i = i + PACKET_HEADER + 1; file_ptr[j] != '\0' ; )
    {
        data[i++] = file_ptr[j++];
    }


    for (j = i; j < PACKET_SIZE + PACKET_HEADER; j++)
    {
        data[j] = 0;
    }
}


/*******************************************************************************
  * @函数名称 Ymodem_PreparePacket
  * @函数说明   准备数据包
  * @输入参数   SourceBuf:数据源缓冲
                data:数据包
                pktNo :数据包编号
                sizeBlk :长度
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
void Ymodem_PreparePacket(u8 *SourceBuf, u8 *data, u8 pktNo, u32 sizeBlk)
{
    u16 i, size, packetSize;
    u8* file_ptr;


    //制作头3个数据包
    packetSize = sizeBlk >= PACKET_1K_SIZE ? PACKET_1K_SIZE : PACKET_SIZE;
    size = sizeBlk < packetSize ? sizeBlk :packetSize;
    if (packetSize == PACKET_1K_SIZE)
    {
        data[0] = STX;
    }
    else
    {
        data[0] = SOH;
    }
    data[1] = pktNo;
    data[2] = (~pktNo);
    file_ptr = SourceBuf;


    //文件名数据包有效数据
    for (i = PACKET_HEADER; i < size + PACKET_HEADER; i++)
    {
        data[i] = *file_ptr++;
    }
    if ( size  <= packetSize)
    {
        for (i = size + PACKET_HEADER; i < packetSize + PACKET_HEADER; i++)
        {
            data[i] = 0x1A; //结束
        }
    }
}


/*******************************************************************************
  * @函数名称 UpdateCRC16
  * @函数说明   更新输入数据的CRC校验
  * @输入参数   crcIn
                byte
  * @输出参数   无
  * @返回参数   CRC校验值
*******************************************************************************/
u16 UpdateCRC16(u16 crcIn, u8 byte)
{
    u32 crc = crcIn;
    u32 in = byte|0x100;
    do
    {
        crc <<= 1;
        in <<= 1;
        if (in&0x100)
            ++crc;
        if (crc&0x10000)
            crc ^= 0x1021;
    }
    while (!(in&0x10000));
    return crc&0xffffu;
}


/*******************************************************************************
  * @函数名称 UpdateCRC16
  * @函数说明   更新输入数据的CRC校验
  * @输入参数   data :数据
                size :长度
  * @输出参数   无
  * @返回参数   CRC校验值
*******************************************************************************/
u16 Cal_CRC16(const u8* data, u32 size)
{
    u32 crc = 0;
    const u8* dataEnd = data+size;
    while (data         crc = UpdateCRC16(crc,*data++);


    crc = UpdateCRC16(crc,0);
    crc = UpdateCRC16(crc,0);
    return crc&0xffffu;
}




/*******************************************************************************
  * @函数名称 CalChecksum
  * @函数说明   计算YModem数据包的总大小
  * @输入参数   data :数据
                size :长度
  * @输出参数   无
  * @返回参数   数据包的总大小
*******************************************************************************/
u8 CalChecksum(const u8* data, u32 size)
{
    u32 sum = 0;
    const u8* dataEnd = data+size;
    while (data < dataEnd )
        sum += *data++;
    return sum&0xffu;
}


/*******************************************************************************
  * @函数名称 Ymodem_SendPacket
  * @函数说明   通过ymodem协议传输一个数据包
  * @输入参数   data :数据地址指针
                length:长度
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
#if 0
void Ymodem_SendPacket(u8 *data, u16 length)
{
    u16 i;
    i = 0;
    while (i < length)
    {
        Send_Byte(data[i]);
        i++;
    }
}


/*******************************************************************************
  * @函数名称 Ymodem_Transmit
  * @函数说明   通过ymodem协议传输一个文件
  * @输入参数   buf :数据地址指针
                sendFileName :文件名
                sizeFile:文件长度
  * @输出参数   无
  * @返回参数   是否成功
                0:成功
*******************************************************************************/
u8 Ymodem_Transmit (u8 *buf, const u8* sendFileName, u32 sizeFile)
{


    u8 packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD];
    u8 FileName[FILE_NAME_LENGTH];
    u8 *buf_ptr, tempCheckSum ;
    u16 tempCRC, blkNumber;
    u8 receivedC[2], CRC16_F = 0, i;
    u32 errors, ackReceived, size = 0, pktSize;


    errors = 0;
    ackReceived = 0;
    for (i = 0; i < (FILE_NAME_LENGTH - 1); i++)
    {
        FileName[i] = sendFileName[i];
    }
    CRC16_F = 1;


    //准备第一个数据包
    Ymodem_PrepareIntialPacket(&packet_data[0], FileName, &sizeFile);


    do
    {
        //发送数据包
        Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER);
        //发送CRC校验
        if (CRC16_F)
        {
            tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE);
            Send_Byte(tempCRC >> 8);
            Send_Byte(tempCRC & 0xFF);
        }
        else
        {
            tempCheckSum = CalChecksum (&packet_data[3], PACKET_SIZE);
            Send_Byte(tempCheckSum);
        }


        //等待响应
        if (Receive_Byte(&receivedC[0], 10000) == 0)
        {
            if (receivedC[0] == ACK)
            {
                //数据包正确传输
                ackReceived = 1;
            }
        }
        else
        {
            errors++;
        }
    } while (!ackReceived && (errors < 0x0A));


    if (errors >=  0x0A)
    {
        return errors;
    }
    buf_ptr = buf;
    size = sizeFile;
    blkNumber = 0x01;


    //1024字节的数据包发送
    while (size)
    {
        //准备下一个数据包
        Ymodem_PreparePacket(buf_ptr, &packet_data[0], blkNumber, size);
        ackReceived = 0;
        receivedC[0]= 0;
        errors = 0;
        do
        {
            //发送下一个数据包
            if (size >= PACKET_1K_SIZE)
            {
                pktSize = PACKET_1K_SIZE;


            }
            else
            {
                pktSize = PACKET_SIZE;
            }
            Ymodem_SendPacket(packet_data, pktSize + PACKET_HEADER);
            //发送CRC校验
            if (CRC16_F)
            {
                tempCRC = Cal_CRC16(&packet_data[3], pktSize);
                Send_Byte(tempCRC >> 8);
                Send_Byte(tempCRC & 0xFF);
            }
            else
            {
                tempCheckSum = CalChecksum (&packet_data[3], pktSize);
                Send_Byte(tempCheckSum);
            }


            //等待响应
            if ((Receive_Byte(&receivedC[0], 100000) == 0)  && (receivedC[0] == ACK))
            {
                ackReceived = 1;
                if (size > pktSize)
                {
                    buf_ptr += pktSize;
                    size -= pktSize;
                    if (blkNumber == (FLASH_IMAGE_SIZE/1024))
                    {
                        return 0xFF; //错误
                    }
                    else
                    {
                        blkNumber++;
                    }
                }
                else
                {
                    buf_ptr += pktSize;
                    size = 0;
                }
            }
            else
            {
                errors++;
            }
        } while (!ackReceived && (errors < 0x0A));
        //如果没响应10次就返回错误
        if (errors >=  0x0A)
        {
            return errors;
        }


    }
    ackReceived = 0;
    receivedC[0] = 0x00;
    errors = 0;
    do
    {
        Send_Byte(EOT);
        //发送 (EOT);
        //等待回应
        if ((Receive_Byte(&receivedC[0], 10000) == 0)  && receivedC[0] == ACK)
        {
            ackReceived = 1;
        }
        else
        {
            errors++;
        }
    } while (!ackReceived && (errors < 0x0A));


    if (errors >=  0x0A)
    {
        return errors;
    }
    //准备最后一个包
    ackReceived = 0;
    receivedC[0] = 0x00;
    errors = 0;


    packet_data[0] = SOH;
    packet_data[1] = 0;
    packet_data [2] = 0xFF;


    for (i = PACKET_HEADER; i < (PACKET_SIZE + PACKET_HEADER); i++)
    {
        packet_data [i] = 0x00;
    }


    do
    {
        //发送数据包
        Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER);
        //发送CRC校验
        tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE);
        Send_Byte(tempCRC >> 8);
        Send_Byte(tempCRC & 0xFF);


        //等待响应
        if (Receive_Byte(&receivedC[0], 10000) == 0)
        {
            if (receivedC[0] == ACK)
            {
                //包传输正确
                ackReceived = 1;
            }
        }
        else
        {
            errors++;
        }


    } while (!ackReceived && (errors < 0x0A));
    //如果没响应10次就返回错误
    if (errors >=  0x0A)
    {
        return errors;
    }


    do
    {
        Send_Byte(EOT);
        //发送 (EOT);
        //等待回应
        if ((Receive_Byte(&receivedC[0], 10000) == 0)  && receivedC[0] == ACK)
        {
            ackReceived = 1;
        }
        else
        {
            errors++;
        }
    } while (!ackReceived && (errors < 0x0A));


    if (errors >=  0x0A)
    {
        return errors;
    }
    return 0;//文件传输成功
}


#endif




void SerialDownload(void)
{
    u8 Number[10] = "          ";
    s32 Size = 0;


    ////SerialPutString("Waiting for the file to be sent ... (press 'a' to abort)\n\r");
    Size = Ymodem_Receive(&tab_1024[0]);
    if (Size > 0)
    {
        SerialPutString("\n\n\r Programming Completed Successfully!\n\r--------------------------------\r\n Name: ");
        SerialPutString(file_name);
        Int2Str(Number, Size);
        SerialPutString("\n\r Size: ");
        SerialPutString(Number);
        SerialPutString(" Bytes\r\n");
        SerialPutString("-------------------\n");
    }
    else if (Size == -1)
    {
        SerialPutString("\n\n\rThe image size is higher than the allowed space memory!\n\r");
    }
    else if (Size == -2)
    {
        SerialPutString("\n\n\rVerification failed!\n\r");
    }
    else if (Size == -3)
    {
        SerialPutString("\r\n\nAborted by user.\n\r");
    }
    else
    {
        SerialPutString("\n\rFailed to receive the file!\n\r");
    }
}
















#endif

/*******************************文件结束***************************************/










/*******************************************************************************
** 文件名: ymodem.c
** 版本:   1.0
** 工作环境: RealView MDK-ARM 4.14
** 作者: wuguoyana
** 生成日期: 2011-04-29
** 功能: 和Ymodem.c的相关的头文件
** 相关文件: stm32f10x.h
** 修改日志: 2011-04-29   创建文档
*******************************************************************************/


/* 防止重定义 *****************************************************************/
#ifndef _YMODEM_H_
#define _YMODEM_H_


#include "stm32f10x.h"
/* 宏 ------------------------------------------------------------------------*/
#define PACKET_SEQNO_INDEX      (1)
#define PACKET_SEQNO_COMP_INDEX (2)


#define PACKET_HEADER           (3)
#define PACKET_TRAILER          (2)
#define PACKET_OVERHEAD         (PACKET_HEADER + PACKET_TRAILER)
#define PACKET_SIZE            (128)
#define PACKET_1K_SIZE      (1024)


#define FILE_NAME_LENGTH    (256)
#define FILE_SIZE_LENGTH        (16)
#define FILE_TYPE (4)


#define SOH                     (0x01)  //128字节数据包开始
#define STX                     (0x02)  //1024字节的数据包开始
#define EOT                     (0x04)  //结束传输
#define ACK                     (0x06)  //回应
#define NAK                     (0x15)  //没回应
#define CA                      (0x18)  //这两个相继中止转移
#define CRC16                   (0x43)  //'C' == 0x43, 需要 16-bit CRC 


#define ABORT1                  (0x41)  //'A' == 0x41, 用户终止 
#define ABORT2                  (0x61)  //'a' == 0x61, 用户终止


#define NAK_TIMEOUT             (0x100000)
#define MAX_ERRORS              (5)


/* 函数声明 ------------------------------------------------------------------*/
s32 Ymodem_Receive (u8 *);
u8 Ymodem_Transmit (u8 *,const  u8* , uint32_t );
void SerialDownload(void);


#endif  /* _YMODEM_H_ */


/*******************************文件结束***************************************/

你可能感兴趣的:(ymodem send file)