ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
5 июля
127508 Топик полностью
AlexandrY (06.08.2008 16:57, просмотров: 258) ответил Evgeny_CD на Коллеги, а не наведет ли кто на исходники YMODEM, адаптированные к микронтроллерным задачам (без широкого использования аццких системных либов и пр.) Неохота тратить врямя на правку исходников из ядра Линуха.
Вот есть 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