Вот есть Ymodem сразу с программированием. Это хидер
#ifndef __LOADER
#define __LOADER
#define PROGRAMM_AREA_BEG_ADDR 0xC0020000 // Начальный адрес области в которой может находится программа пользователя
#define PROGRAMM_AREA_END_ADDR 0xC011FFFF // Конечный адрес области в которой может находится программа пользователя
#define APP_START_ADDR 0xC0020000 // Адрес с которого стартует приложение пользователя
#define FLASH_BLOCK_SIZE 0x20000 // 128 KB
#define MAX_FILE_SIZE 0x100000
#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 SOH (0x01) /* start of 128-byte data packet */
#define STX (0x02) /* start of 1024-byte data packet */
#define EOT (0x04) /* end of transmission */
#define ACK (0x06) /* acknowledge */
#define NAK (0x15) /* negative acknowledge */
#define CA (0x18) /* two of these in succession aborts transfer */
#define CRC16 (0x43) /* 'C' == 0x43, request 16-bit CRC */
#define ABORT1 (0x41) /* 'A' == 0x41, abort by user */
#define ABORT2 (0x61) /* 'a' == 0x61, abort by user */
#define NAK_TIMEOUT (0x5000)
#define MAX_ERRORS (5)
INT32S Programm_by_Ymodem (void);
#endif
Это сам модуль
#define RCV_OK 0
#define RCV_ERROR -1
#define RCV_ABORT 1
/*-------------------------------------------------------------------------------------------------------------
Ожидать возможности записать байт в UART
-------------------------------------------------------------------------------------------------------------*/
void UART_wait_TX_occasion(UART_TypeDef *puart)
{
while ( puart->USR1->TRDY ==0); // Ждать пока в FIFO UART-а появится свободное место
}
/*-------------------------------------------------------------------------------------------------------------
Запись байта b в pdefuart
-------------------------------------------------------------------------------------------------------------*/
void UART_TX_byte(INT8U b)
{
if ( pdefuart==0 ) return;
UART_wait_TX_occasion(pdefuart);
pdefuart->UTXD->TX_DATA = b; // Запись в регистр данных UART
}
/*-------------------------------------------------------------------------------------------------------------
Чтение байта b из pdefuart
-------------------------------------------------------------------------------------------------------------*/
INT8U UART_RX_byte(void)
{
while ( pdefuart->USR2->RDR == 0 );
return (pdefuart->URXD->RX_DATA);
}
/*-------------------------------------------------------------------------------------------------------------
Взять байт из UART без ожидания
-------------------------------------------------------------------------------------------------------------*/
INT32U UART_peek_byte(INT8U *b)
{
if ( pdefuart->USR2->RDR == 0 ) // Проверка в регистре статуса на наличие данных
{
return (0);
}
else
{
*b = (INT8U)pdefuart->URXD->RX_DATA; // Чтение регистра данных UART
return (1);
}
}
/*-------------------------------------------------------------------------------------------------------------
Ожидание приема символа UART-ом
Параметры: c - принятый символ
timeout - время ожидания с дискретностью 10 мкс
Возвращает: 0 - Если байт принят
-1 - в случае таймаута
-------------------------------------------------------------------------------------------------------------*/
INT32S UART_wait_byte (INT8U *c, INT32U timeout)
{
while ( timeout-- > 0 )
{
if ( UART_peek_byte(c) == 1 )
{
return (0);
}
US_DELAY(10);
}
return (-1);
}
/*-------------------------------------------------------------------------------------------------------------
Function Name : Receive_Packet
Description : Receive a packet from sender
Input 1 : - data
Input 2 : - length
Input 3 : - timeout
Output : *length:
0: end of transmission
-1: abort by sender
>0: packet length
Return : 0: normally return
-1: timeout or packet error
1: abort by user
-------------------------------------------------------------------------------------------------------------*/
static INT32S Wait_Ymodem_packet (INT8U *data, INT32S *length, INT32U timeout)
{
INT16U i, packet_size;
INT8U c;
*length = 0;
if ( UART_wait_byte(&c, timeout) != 0 ) return (RCV_ERROR);
switch ( c )
{
case SOH:
packet_size = PACKET_SIZE;
break;
case STX:
packet_size = PACKET_1K_SIZE;
break;
case EOT:
return (RCV_OK);
case CA:
if ( (UART_wait_byte(&c, timeout) == 0) && (c == CA) )
{
*length = -1;
return (RCV_OK);
}
else
{
return (RCV_ERROR);
}
case ABORT1:
case ABORT2:
return (RCV_ABORT);
default:
return (RCV_ERROR);
}
*data = c;
for ( i = 1; i < (packet_size + PACKET_OVERHEAD); i ++ )
{
if ( UART_wait_byte(data + i, timeout) != 0 )
{
return (RCV_ERROR);
}
}
if ( data[PACKET_SEQNO_INDEX] != ((data[PACKET_SEQNO_COMP_INDEX] ^ 0xff) & 0xff) )
{
return (RCV_ERROR);
}
*length = packet_size;
return (RCV_OK);
}
/*-------------------------------------------------------------------------------------------------------------
Прием пакетов по Y-Modem и программирование во FLASH микроконтроллера
-------------------------------------------------------------------------------------------------------------*/
INT32S Programm_by_Ymodem (void)
{
INT8U *file_ptr;
INT8U *buf_ptr = packet_data;
INT32S i;
INT32S pack_len;
INT32S session_done;
INT32S file_done;
INT32S packets_received;
INT32S errors;
INT32S session_begin;
INT32S size = 0;
session_done = 0;
errors = 0;
session_begin = 0;
while ( 1 )
{
packets_received = 0;
file_done = 0;
while ( 1 )
{
switch ( Wait_Ymodem_packet(packet_data, &pack_len, NAK_TIMEOUT) )
{
case RCV_OK:
errors = 0;
switch ( pack_len )
{
case - 1: /* Abort by sender */
UART_TX_byte(ACK);
return (0);
case 0: /* End of transmission */
UART_TX_byte(ACK);
file_done = 1;
break;
default: /* Normal packet */
if ( (packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff) )
{
UART_TX_byte(NAK);
}
else
{
if ( packets_received == 0 ) /* Filename packet */
{
if ( packet_data[PACKET_HEADER] != 0 ) /* Filename packet has valid data */
{
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';
for ( i = 0, file_ptr ++; (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH); )
{
file_size[i++] = *file_ptr++;
}
file_size[i++] = '\0';
Str2Int(file_size, &size);
if ( size > MAX_FILE_SIZE ) // Проверить размер файла для записи
{
UART_TX_byte(CA); // Завершаем сессию в случае ошибки
UART_TX_byte(CA);
return (0);
}
// Стереть сегменты FLASH для последующего программирования
if (Sectors_Erasing()!=0)
{
UART_TX_byte(CA); // Завершаем сессию в случае ошибки
UART_TX_byte(CA);
return (0);
}
flash_ptr = PROGRAMM_AREA_BEG_ADDR;
for ( i=0;i<128;i++ ) // Проверка первых байт памяти на стирание.
{
if ( *(INT16U*)(flash_ptr+i*2)!=0xFFFF )
{
UART_TX_byte(CA); // Завершаем сессию в случае ошибки
UART_TX_byte(CA);
return (0);
}
}
UART_TX_byte(ACK); // Продолжаем сессию
UART_TX_byte(CRC16);
// Иницализировать начальный вектор для дешифровки
/*
{
INT8U *p = chainCipherBlock;
INT8U const *q = INITIAL_VECTOR;
INT8U n = 16;
do
{
*p++ = *q++;
}
while ( --n );
}
aesInit(); // Init AES algorithm.
*/
}
else
{
UART_TX_byte(ACK); // Пустой пакет, завершаем сессию
file_done = 1;
session_done = 1;
break;
}
}
else /* Data packet */
{
buf_ptr = packet_data + PACKET_HEADER;
// Принят пакет длиной pack_len в буфер buf_ptr
/*
{ // Расшифровать принятый пакет
INT8U *p = buf_ptr;
INT16U sz = pack_len;
do
{
aesDecrypt(p, chainCipherBlock);
p += 16;
}
while ( sz -= 16 );
}
*/
memcpy(prg_data,buf_ptr,pack_len);
if (ProgramPage(flash_ptr,pack_len,prg_data)!=0)
{
UART_TX_byte(CA);
UART_TX_byte(CA);
return (0);
}
flash_ptr += pack_len;
UART_TX_byte(ACK);
}
packets_received ++;
session_begin = 1;
}
}
break;
case RCV_ABORT:
UART_TX_byte(CA);
UART_TX_byte(CA);
return (0);
default:
if ( session_begin > 0 )
{
errors ++;
}
if ( errors > MAX_ERRORS )
{
UART_TX_byte(CA);
UART_TX_byte(CA);
return (0);
}
UART_TX_byte(CRC16);
break;
} // switch( Wait_Ymodem_packet(packet_data, &packet_length, NAK_TIMEOUT) )
if ( file_done != 0 )
{
INT16U crc;
// Запись файла окончена, записать контрольную сумму
crc = GetBlockCRC_by_tbl((INT8U*)PROGRAMM_AREA_BEG_ADDR,PROGRAMM_AREA_END_ADDR - PROGRAMM_AREA_BEG_ADDR - 1,0xFFFF);
flash_ptr = PROGRAMM_AREA_END_ADDR - 1;
memcpy((void*)prg_data, (void*)(flash_ptr & 0xFFFFFFC0), 64);
prg_data[62] = crc & 0xFF;
prg_data[63] = crc >> 8;
if (ProgramPage(flash_ptr & 0xFFFFFFC0,64,prg_data)!=0)
{
UART_TX_byte(CA);
UART_TX_byte(CA);
return (0);
}
if ( *(INT16U*)flash_ptr != crc ) return (0);
break;
}
} // while( 1 )
if ( session_done != 0 )
{
break;
}
}
return(INT32S)size;
}
INDEMSYS
-
- Спасибо! Вы, как всегда, выручили. - Evgeny_CD(06.08.2008 17:00)
- А еще маленький вопрос - а есть ли где внятное описание YMODEM? А то все какие-то хакерские тексты попадаются. - Evgeny_CD(06.08.2008 17:02)
- эта ж микрософтская шняга, мне, когда-то помогло - yes(15.08.2008 16:48, ссылка)
- Yes!! :) Это то, что я искал. Надо признать, что MSDN очень хорошая штука. Я ламер, что редко туда заглядываю! - Evgeny_CD(15.08.2008 16:58)
- Даж не знаю, я этот кусок позаимствовал у Atmel-а в свое время. AlexandrY(65 знак., 06.08.2008 17:12)
- эта ж микрософтская шняга, мне, когда-то помогло - yes(15.08.2008 16:48, ссылка)
- А еще маленький вопрос - а есть ли где внятное описание YMODEM? А то все какие-то хакерские тексты попадаются. - Evgeny_CD(06.08.2008 17:02)
- Спасибо! Вы, как всегда, выручили. - Evgeny_CD(06.08.2008 17:00)