Ika Shouyu Poppoyaki - LPC82x supported
Fork of ika_shouyu_poppoyaki by
main.cpp
- Committer:
- okano
- Date:
- 2013-09-09
- Revision:
- 17:339f40a14f67
- Parent:
- 16:cac2348cfcfb
- Child:
- 18:b401da200216
File content as of revision 17:339f40a14f67:
/** * Sample of ISP operation for NXP MCUs * * @author Tedd OKANO * @version 0.7 * @date Aug-2013 * * This program programs MCU flash memory through UART. It uses * "In-System Programming (ISP)" interface in target MCU (NXP LPC micro- * controllers). * * The ISP is done by PC and serial cable normally. The ISP protocol is * executed software on a PC. The software reads a data file and transfers * the data with the ISP protocol. * This program does same process of that. The mbed perform the function like * "FlashMagic" and "lpc21isp". * (This program not just copies the binary but also insert 4 byte checksum at * address 0x1C.) * * This program currently supports LPC1114(LPC1114FN28/102 - DIP28-ARM) and * LPC810(LPC810M021FN8 - DIP8-ARM). */ #include "mbed.h" #include "target_table.h" BusOut leds( LED4, LED3, LED2, LED1 ); DigitalOut reset_pin( p26 ); DigitalOut isp_pin( p25 ); Serial target ( p28, p27 ); Serial pc ( USBTX,USBRX ); LocalFileSystem local( "local" ); Ticker success; #define ENTER_TO_ISP_MODE 0 #define NO_ISP_MODE 1 #define STR_BUFF_SIZE 64 #define SOURCE_FILE "/local/bin" #define ISP_BAUD_RATE 115200 //#define ISP_BAUD_RATE 57600 //#define ISP_BAUD_RATE 9600 #define TARGET_OPERATION_BAUD_RATE 9600 int error_state = 0; int file_size( FILE *fp ); void reset_target( int isp_pin_state ); int try_and_check( char *command, char *expected_return_str, int mode ); int try_and_check2( char *command, char *expected_return_str, int mode ); void print_command( char *command ); void print_result( int r ); char read_byte( void ); void erase_sectors( int last_sector ); int write_uuencoded_data( FILE *fp, int ram_size, int sector_size, unsigned int ); int write_binary_data( FILE *fp, int ram_size, int sector_size, unsigned int ram_start ); void initialize_uue_table( void ); long bin2uue( char *bin, char *str, int size ); int get_flash_writing_size( int ram_size, unsigned int ram_start ); void add_isp_checksum( char *b ); void send_RAM_transfer_checksum( int checksum ); void put_string( char *s ); void put_binary( char *b, int size ); void get_string( char *s ); void success_indicator(); #pragma diag_suppress 1293 // surpressing a warning message of "assignment in condition" ;) int main() { FILE *fp; char str_buf0[ STR_BUFF_SIZE ]; char str_buf1[ STR_BUFF_SIZE ]; int data_size; int last_sector; target_param *tpp; printf( "\r\n\r\n\r\nmbed ISP program : programming LPC device from mbed\r\n" ); target.baud( ISP_BAUD_RATE ); reset_target( ENTER_TO_ISP_MODE ); try_and_check( "?", "Synchronized", 0 ); try_and_check2( "Synchronized\r\n", "OK", 0 ); try_and_check2( "12000\r\n", "OK", 0 ); try_and_check2( "U 23130\r\n", "0", 0 ); try_and_check2( "A 0\r\n", "0", 0 ); try_and_check( "K\r\n", "0", 0 ); get_string( str_buf0 ); get_string( str_buf1 ); printf( " result of \"K\" = %s %s\r\n", str_buf0, str_buf1 ); try_and_check( "J\r\n", "0", 0 ); get_string( str_buf0 ); printf( " result of \"J\" = %s\r\n", str_buf0 ); tpp = find_target_param( str_buf0 ); printf( " target device found : type = \"%s\"\r\n", tpp->type_name ); printf( " ID = 0x%08X\r\n", tpp->id ); printf( " RAM size = %10d bytes\r\n", tpp->ram_size ); printf( " flash size = %10d bytes\r\n", tpp->flash_size ); printf( " opening file: \"%s\"\r\n", SOURCE_FILE ); if ( NULL == (fp = fopen( SOURCE_FILE, "rb" )) ) { error( "couldn't open source file" ); return ( 1 ); } data_size = file_size( fp ); last_sector = data_size / tpp->sector_size; printf( " data size = %d bytes, it takes %d secotrs in flash area\r\n", data_size, last_sector + 1 ); printf( " resetting target\r\n" ); erase_sectors( last_sector ); if ( tpp->write_type == BINARY ) write_binary_data( fp, tpp->ram_size, tpp->sector_size, tpp->ram_start_address ); else // UUENCODE write_uuencoded_data( fp, tpp->ram_size, tpp->sector_size, tpp->ram_start_address ); fclose( fp ); printf( "\r\n %s\r\n\r\n", error_state ? "** The data could not be written :(" : "** The data has been written successflly :)" ); #define AUTO_PROGRAM_START #ifdef AUTO_PROGRAM_START target.baud( TARGET_OPERATION_BAUD_RATE ); reset_target( NO_ISP_MODE ); printf( " ** The program in flash has been started!!\r\n" ); #endif printf( " (now the mbed is working in \"serial through mode\")\r\n\r\n" ); success.attach( &success_indicator, 0.1 ); while (1) { if ( pc.readable() ) { target.putc( pc.getc() ); } if ( target.readable() ) { pc.putc( target.getc() ); } } } int file_size( FILE *fp ) { int size; fseek( fp, 0, SEEK_END ); // seek to end of file size = ftell( fp ); // get current file pointer fseek( fp, 0, SEEK_SET ); // seek back to beginning of file return size; } void reset_target( int isp_pin_state ) { reset_pin = 1; isp_pin = isp_pin_state; wait_ms( 100 ); reset_pin = 0; wait_ms( 100 ); reset_pin = 1; wait_ms( 100 ); } int try_and_check( char *command, char *expected_return_str, int mode ) { char rtn_str[ STR_BUFF_SIZE ]; int result = 1; print_command( command ); put_string( command ); get_string( rtn_str ); print_result( result = strcmp( expected_return_str, rtn_str ) ); if ( result && !mode ) error( "command failed\r\n" ); error_state |= result; return ( result ); } int try_and_check2( char *command, char *expected_return_str, int mode ) { char rtn_str[ STR_BUFF_SIZE ]; int result = 1; print_command( command ); put_string( command ); get_string( rtn_str ); // just readout echoback get_string( rtn_str ); print_result( result = strcmp( expected_return_str, rtn_str ) ); if ( result && !mode ) error( "command failed\r\n" ); error_state |= result; return ( result ); } void print_command( char *command ) { char s[ STR_BUFF_SIZE ]; char *pos; strcpy( s, command ); if ( pos = strchr( s, '\r' ) ) *pos = '\0'; if ( pos = strchr( s, '\n' ) ) *pos = '\0'; printf( " command-\"%s\" : ", s ); } void print_result( int r ) { printf( "%s\r\n", r ? "Fail" : "Pass" ); } char read_byte( void ) { while ( !target.readable() ) ; return ( target.getc() ); } void erase_sectors( int last_sector ) { char command_str[ STR_BUFF_SIZE ]; sprintf( command_str, "P 0 %d\r\n", last_sector ); try_and_check( command_str, "0", 0 ); *(command_str) = 'E'; try_and_check( command_str, "0", 0 ); } #define BYTES_PER_LINE 45 char uue_table[ 64 ]; int write_uuencoded_data( FILE *fp, int ram_size, int sector_size, unsigned int ram_start ) { char command_str[ STR_BUFF_SIZE ]; long checksum = 0; int total_size = 0; int size; int flash_writing_size; int lines_per_transfer; int transfer_size; char *b; initialize_uue_table(); flash_writing_size = get_flash_writing_size( ram_size, ram_start ); lines_per_transfer = ((flash_writing_size / BYTES_PER_LINE) + 1); transfer_size = (((flash_writing_size + 11) / 12) * 12); // char b[ transfer_size ]; // this can be done in mbed-compiler. but I should do it in common way if ( NULL == (b = (char *)malloc( transfer_size * sizeof( char ) )) ) error( "malloc error happened\r\n" ); for ( int i = flash_writing_size; i < transfer_size; i++ ) b[ i ] = 0; // this is not neccesary but just stuffing stuffing bytes while ( size = fread( b, sizeof( char ), flash_writing_size, fp ) ) { if ( !total_size ) { // overwriting 4 bytes data for address=0x1C // there is a slot for checksum that is checked in (target's) boot process add_isp_checksum( b ); } sprintf( command_str, "W %ld %ld\r\n", ram_start, transfer_size ); try_and_check( command_str, "0", 0 ); for ( int i = 0; i < lines_per_transfer; i++ ) { checksum += bin2uue( b + (i * BYTES_PER_LINE), command_str, i == (lines_per_transfer - 1) ? (transfer_size % BYTES_PER_LINE) : BYTES_PER_LINE ); // printf( " data -- %02d %s\r", i, command_str ); put_string( command_str ); if ( !((i + 1) % 20) ) { send_RAM_transfer_checksum( checksum ); checksum = 0; } } send_RAM_transfer_checksum( checksum ); checksum = 0; sprintf( command_str, "P %d %d\r\n", total_size / sector_size, total_size / sector_size ); try_and_check( command_str, "0", 0 ); sprintf( command_str, "C %d %d %d\r\n", total_size, ram_start, flash_writing_size ); try_and_check( command_str, "0", 0 ); total_size += size; } try_and_check( "G 0 T\r\n", "0", 0 ); free( b ); return ( total_size ); } int write_binary_data( FILE *fp, int ram_size, int sector_size, unsigned int ram_start ) { char command_str[ STR_BUFF_SIZE ]; int total_size = 0; int size; int flash_writing_size; char *b; flash_writing_size = 256; if ( NULL == (b = (char *)malloc( flash_writing_size * sizeof( char ) )) ) error( "malloc error happened\r\n" ); while ( size = fread( b, sizeof( char ), flash_writing_size, fp ) ) { if ( !total_size ) { // overwriting 4 bytes data for address=0x1C // there is a slot for checksum that is checked in (target's) boot process add_isp_checksum( b ); } sprintf( command_str, "W %ld %ld\r\n", ram_start, flash_writing_size ); try_and_check( command_str, "0", 0 ); put_binary( b, flash_writing_size ); put_string( "\r\n" ); sprintf( command_str, "P %d %d\r\n", total_size / sector_size, total_size / sector_size ); try_and_check( command_str, "0", 0 ); sprintf( command_str, "C %d %d %d\r\n", total_size, ram_start, flash_writing_size ); try_and_check( command_str, "0", 0 ); total_size += size; printf( " total %d bytes transferred\r", total_size ); } free( b ); return ( total_size ); } void initialize_uue_table( void ) { int i; uue_table[0] = 0x60; // 0x20 is translated to 0x60 ! for (i = 1; i < 64; i++) { uue_table[i] = (char)(0x20 + i); } } long bin2uue( char *bin, char *str, int size ) { unsigned long v; long checksum = 0; int strpos = 0; *(str + strpos++) = ' ' + size; for ( int i = 0; i < size; i += 3 ) { checksum += *(bin + i + 0) + *(bin + i + 1) + *(bin + i + 2); v = (*(bin + i + 0) << 16) | (*(bin + i + 1) << 8) | (*(bin + i + 2) << 0); *(str + strpos++) = uue_table[ (v >> 18) & 0x3F ]; *(str + strpos++) = uue_table[ (v >> 12) & 0x3F ]; *(str + strpos++) = uue_table[ (v >> 6) & 0x3F ]; *(str + strpos++) = uue_table[ (v >> 0) & 0x3F ]; } *(str + strpos++) = '\n'; *(str + strpos++) = '\0'; return checksum; } int get_flash_writing_size( int ram_size, unsigned int ram_start ) { int flash_writing_size[] = { 4096, 1024, 512, 256 }; int available_size; int i; available_size = ram_size - (ram_start & 0xFFFF); for ( i = 0; i < sizeof( flash_writing_size ) / sizeof( int ); i++ ) { if ( flash_writing_size[ i ] < available_size ) break; } return ( flash_writing_size[ i ] ); } void add_isp_checksum( char *b ) { // see http://www.lpcware.com/content/nxpfile/lpc177x8x-checksum-insertion-program unsigned int *p; unsigned int cksum = 0; p = (unsigned int *)b; for ( int i = 0; i < 7; i++ ) { cksum += *p++; } printf( " -- value at checksum slot : 0x%08X\r\n", *p ); *p = 0xFFFFFFFF - cksum + 1; printf( " -- calculated checksum : 0x%08X\r\n", *p ); printf( " new checksum will be used to program flash\r\n" ); } void send_RAM_transfer_checksum( int checksum ) { char command[ 16 ]; sprintf( command, "%d\n", checksum ); try_and_check( command, "OK", 0 ); } void put_string( char *s ) { char c; static int i = 0; while ( c = *s++ ) { target.putc( c ); leds = i++ & 0x1; } } void put_binary( char *b, int size ) { for ( int i = 0; i < size; i++ ) target.putc( *b++ ); } Timeout timeout; int timeout_flag = 0; void set_flag() { timeout_flag = 1; } void get_string( char *s ) { int i = 0; char c = 0; timeout_flag = 0; timeout.attach( &set_flag, 1 ); do { do { if ( target.readable() ) { c = target.getc(); if ( ( c == '\n') || (c == '\r') ) break; *s++ = c; i++; } if ( timeout_flag ) return; } while ( 1 ); } while ( !i ); *s = '\0'; } void success_indicator() { static int i = 0; leds = 0x1 << (i++ & 0x3); }