this transfers data (which is stored in "bin" file in mbed storage) into LPC1114, LPC1115, LPC81x, LPC82x, LPC1768/LPC1769 and LPC11U68/LPC11E68 internal flash memory through ISP.

Dependencies:   mbed MODSERIAL DirectoryList

Information

日本語版がこのページ下半分にあります!

Japanese version is available lower half of this page.

Caution!

このプログラムでイカを焼くことはできません (^ ^;

"Ika-shouyu-poppoyaki" is a name of Japanese local food.
If I try to do a direct translation, it will be something like "Choo-choo grilled calamari with soy-sauce".
However, you may noticed already, it cannot be grilled by this program ;-)

ISP programming application on mbed

ISP program writes data into flash memory of target MCU.

This mbed program programs target 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 with 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 performs a function like "FlashMagic" or "lpc21isp".
(This program does not just copy the binary but also insert 4 byte checksum at address 0x1C.)

This program currently supports LPC1114, LPC1115, LPC81x, LPC82x, LPC1768/LPC1769 and LPC11U68/LPC11E68.

Information

For the LPC1768 and LPC1769, this program supports writing only. It cannot perform verifying.

Modification for targeting LPC82x series has been done by Mr. k4zuki. Thank you very much!
Modification for targeting LPC11U68/LPC11E68 has been done by HAPI- Tech. Thank you very much!!

/media/uploads/okano/copying_bin_e.png

How to execute

With this program, all you need to do is..

  1. Connect the mbed and the target (/RESET and /ISP_enable signals in are option. Those are not necessary if you set the target ISP mode manually)
  2. Rename your (binary) file to "bin" and copy into the mbed storage.
  3. Press reset button of mbed.
  • When the program completed successfully, you will find the LEDs on mbed blinks sequentially (LED1→LED2→LED3→LED4).
  • If it failed, the mbed reports it "Runtime error" by LEDs.
  • You can also monitor the progress and result on a terminal screen (mbed reports those by printf).
  • if you enabled "AUTO_PROGRAM_START", the program in the target will be started automatically.
  • from version 0.7, this program works as "USB-serial bridge" after the ISP writing done. The serial enabled target program (and if "AUTO_PROGRAM_START" is enabled, ) the UART will come up on the terminal screen after ISP completion. Please set "TARGET_OPERATION_BAUD_RATE" as baud rate of target program. The ISP speed can be set by "ISP_BAUD_RATE" separately.

/media/uploads/okano/files_in_storage_e.png

Information

If you don't have a file named "bin", the program will ask you which file you want to choose.
You will find a list of files on PC terminal and that interface let you select a file as source.
(The file names will appear in 8.3 format like old DOS.)

There are some options to bypassing the ISP to execute USB-serial through mode or erasing flash.

If there is a "bin" file, the program may work as usual.
(updated on 29-Jan-2015)

Sample of operation

Next picture is sample of the operation.

  1. The target (LPC1114) goes into ISP mode after first reset.
  2. mbed writes binary into flash in the target (binary size is 12668 bytes in this sample).
  3. when the writing completed, mbed starts reading the flash. the data is verified by comparing with original file.
  4. Asserting reset again with "ISP_enable pin" HIGH.
  5. The target starts to work with written binary (program). In this sample, the target sending character data on UART and toggling LED (GPIO) pin periodically.

/media/uploads/okano/isp_operation_sample_1114_e2.png

Recipe for adding chip support

Information

This section had been written by At_Zamasu_Zansu.
Thank you!

Describing how to add a target device.
Register new Device ID in target_table.cpp.

Targets defined in target_table.cpp.

target_table.cpp

target_param    target_table[]  = {
    { "unknown ttarget",        0xFFFFFFFF, 1024,    4096, 4096, UUENCODE, 0x10000200 },
    { "LPC1114FN28(FDH28)/102", 0x0A40902B, 4096,   32768, 4096, UUENCODE, 0x10000200 },
    { "LPC1114FN28(FDH28)/102", 0x1A40902B, 4096,   32768, 4096, UUENCODE, 0x10000200 },
    { "LPC810M021FN8",          0x00008100, 1024,    4096, 1024, BINARY,   0x10000300 },
    { "LPC811M001JDH16",        0x00008110, 2048,    8192, 1024, BINARY,   0x10000300 },
    { "LPC812M101JDH16",        0x00008120, 4096,   16384, 1024, BINARY,   0x10000300 },
    { "LPC812M101JD20",         0x00008121, 4096,   16384, 1024, BINARY,   0x10000300 },
    { "LPC812M101JDH20",        0x00008122, 4096,   16384, 1024, BINARY,   0x10000300 },
///added for LPC82x series
    { "LPC824M201JHI33",        0x00008241, 8192,   32768, 1024, BINARY,   0x10000300 },
    { "LPC822M101JHI33",        0x00008221, 4096,   16384, 1024, BINARY,   0x10000300 },
    { "LPC824M201JDH20",        0x00008242, 8192,   32768, 1024, BINARY,   0x10000300 },
    { "LPC822M101JDH20",        0x00008222, 4096,   16384, 1024, BINARY,   0x10000300 },
 
};

Structure of the table is defined in target_table.h.

target_table.h

typedef struct  taget_param_st {
    char            *type_name;
    int             id;
    int             ram_size;
    int             flash_size;
    int             sector_size;
    int             write_type;
    unsigned int    ram_start_address;
}

Items are defined in order of next sample in target_table.cpp

 {type_name, id, ram_size, flash_size, sector_size, write_type, ram_start_address}

Sample of how to do this

Data can be found in usermanual(UM) and datasheet. An example following.

In case of LPC82xx
UM10800 LPC82x User manual http://www.nxp.com/documents/user_manual/UM10800.pdf
LPC82x Product data sheet http://www.nxp.com/documents/data_sheet/LPC82X.pdf

  • type_name:
    • Table 322. Part identification numbers can be found by searching in UM. Pick up a device from the Table 322.
  • id:
    • Put a Hex coding value in Table 322.
  • ram_size:
    • Put target RAM size which can be found in datasheet by searching "Ordering options". Find the RAM size in Table2 (in bytes)
  • flash_size:
    • Put target flash size from the Table 2.
      The size should be calculated as "1KB = 1024" bytes.
  • sector_size:
    • A description of "The size of a sector is 1 KB and the size of a page is 64 Byte. One sector contains 16 pages" can be found in 25.5 General description, UM. Pick up taeget sector size and put it into the table in bytes. In this case, it will be 1024.
    • In case of LPC176x, the secotr size is 4KB for first 16 sectors and rest are 32K. So it cannot be defined by single value. For this type of targets, prepare a special value for the sector size. The program calculates the size when this value is detected.
  • ram_start_address:
    • Put an address of example which can be found by searching "UART ISP Write to RAM command" or "Write to RAM" in UM

Reference




イカ醤油ポッポ焼き

mbed用ISPプログラム

NXP製のマイコンは,内部フラッシュメモリへのプログラムの書き込みをUART経由で行うことができます.
通常,この作業はPC上のソフトウェア(たとえば"FlashMagic""lpc21isp"など)を用いて,PC上のファイルのデータを,UARTで接続したマイコンの内蔵フラッシュに書き込みます.

「イカ醤油ポッポ焼き」はmbedでそれらのソフトの代わりをさせるものです.mbedストレージ内に置いた「bin」と名付けられたファイルを読み,フラッシュへ書き込みます.
この書き込みを行う際には,アドレス0x1Cに置いておく必要のある4バイトのチェックサムも自動で追加されます.

現在サポートしているターゲットはLPC1114LPC1115LPC81xLPC82xLPC1768/LPC1769LPC11U68/LPC11E68です.

Information

LPC1768 and LPC1769 では書き込みのみがサポートされます.読み出し検証は実行されません.

LPC82xシリーズをターゲットとするための変更k4zukiさんがしてくださいました.ありがとうございます!
LPC11U68/LPC11E68をターゲットとするための変更HAPI- Techさんがしてくださいました.ありがとうございます!

/media/uploads/okano/copying_bin_j.png

美味しい料理法

このプログラムの動かし方は次の通り

  1. mbedとターゲット(書き込み対象のマイコン)を接続する (ターゲットを手動でISPモードに入れる場合には,/RESET と /ISP_enable は接続する必要はありません)
  2. 書き込みたいファイル(バイナリフォーマット)の名前を「bin」に変更して,mbed内にコピー
  3. mbedのリセットボタンを押す
  • 書き込みが無事に終了するとmbed上のLEDが順番に点滅を繰り返します(LED1→LED2→LED3→LED4).
  • もし何らかのエラーが発生して失敗した場合には"Runtime error"が発生した時のLED点灯となります.
  • またコンピュータのターミナルで状況や結果を確認することもできます(mbedがprintfで状況を出力しています)
  • "AUTO_PROGRAM_START"を有効にしてあれば,書き込み終了後,ターゲットのプログラムは自動的にスタートします.
  • バージョン0.7以降,このプログラムはISP書き込みの終了後にUSB-Serialブリッジとして動作するようにしてあります.ターゲットのプログラムがシリアルを使うもので(かつ"AUTO_PROGRAM_START"が有効で)あれば,入出力はそのままISP完了後のターミナルに現れます."TARGET_OPERATION_BAUD_RATE"はターゲットのプログラムが使うボーレートに合わせてください.ISPの書き込みに使うボーレートは "これとは別に"ISP_BAUD_RATE"で指定することができます.

/media/uploads/okano/files_in_storage_j2.png

Information

もし「bin」と名付けられたファイルが見つからなければ,(PCターミナル上で)どのファイルを選択するかが訊ねられます.
その表示を確認して,どのファイルを書き込むのかを選択してください.
「bin」ファイルが有れば,これまでと同じように動作します.(ファイル名はDOSのような8.3フォーマットで表示されます)

この他,ISPをバイパスしてシリアススルー・モードに行ったり,フラッシュを消すだけという操作も可能になっています.

(2015年1月29日にアップデートされました)

動作の例

次の図は動作の例です

  1. 最初のリセットによってターゲット(LPC1114)がISPモードに入ります
  2. mbedがターゲットのフラッシュにバイナリを書き込みます(この例では12668バイトのバイナリを書いています)
  3. 書き込みが終わるとフラッシュの読み出しを始めます.このデータを元のファイルとの比較し,検証を行います
  4. ISPイネーブル・ピンをHIGHにして再度リセットを行います
  5. ターゲットは書き込まれたプログラムの実行を開始します.この例ではターゲットは周期的にUARTへ文字データを送り,LEDを(GPIOピン)を点滅させます
  6. The target starts to work with written binary (program). The target sending character data on UART and toggling LED (GPIO) pin periodically.

/media/uploads/okano/isp_operation_sample_1114_j2.png


イカ醤油ポッポ焼き味付けレシピ

Information

この節はざますざんすさんが作成してくれました.
ありがとうございます!

これは,イカ醤油ポッポ焼きに新しいターゲットデバイスを追加する場合のレシピを纏めたものです.

必要事項:target_table.cpp へ新しいDevice ID register を追加する.

target_table.cppに記載されているターゲット一覧.

target_table.cpp

target_param    target_table[]  = {
    { "unknown ttarget",        0xFFFFFFFF, 1024,    4096, 4096, UUENCODE, 0x10000200 },
    { "LPC1114FN28(FDH28)/102", 0x0A40902B, 4096,   32768, 4096, UUENCODE, 0x10000200 },
    { "LPC1114FN28(FDH28)/102", 0x1A40902B, 4096,   32768, 4096, UUENCODE, 0x10000200 },
    { "LPC810M021FN8",          0x00008100, 1024,    4096, 1024, BINARY,   0x10000300 },
    { "LPC811M001JDH16",        0x00008110, 2048,    8192, 1024, BINARY,   0x10000300 },
    { "LPC812M101JDH16",        0x00008120, 4096,   16384, 1024, BINARY,   0x10000300 },
    { "LPC812M101JD20",         0x00008121, 4096,   16384, 1024, BINARY,   0x10000300 },
    { "LPC812M101JDH20",        0x00008122, 4096,   16384, 1024, BINARY,   0x10000300 },
///added for LPC82x series
    { "LPC824M201JHI33",        0x00008241, 8192,   32768, 1024, BINARY,   0x10000300 },
    { "LPC822M101JHI33",        0x00008221, 4096,   16384, 1024, BINARY,   0x10000300 },
    { "LPC824M201JDH20",        0x00008242, 8192,   32768, 1024, BINARY,   0x10000300 },
    { "LPC822M101JDH20",        0x00008222, 4096,   16384, 1024, BINARY,   0x10000300 },
 
};

上記コードは以下の構造を取っている.target_table.h に以下のコードがある.

target_table.h

typedef struct  taget_param_st {
    char            *type_name;
    int             id;
    int             ram_size;
    int             flash_size;
    int             sector_size;
    int             write_type;
    unsigned int    ram_start_address;
}

以下の順番にtarget_table.cppにコーディングする.

 {type_name, id, ram_size, flash_size, sector_size, write_type, ram_start_address}

作業の手順例

データはユーザマニュアル(UM)と Data sheet から検索する.以下に例を上げる.

LPC82xxの場合
UM10800 LPC82x User manual http://www.nxp.com/documents/user_manual/UM10800.pdf
LPC82x Product data sheet http://www.nxp.com/documents/data_sheet/LPC82X.pdf

  • type_name:
    • UMから Part identification numbers を検索すると,Table 322. Part identification numbersが現れる.Table 322より Table記載のDeviceを入力.
  • id:
    • UMから Part identification numbers を検索,Table 322. よりHex codingを入力.
  • ram_size:
    • Product data sheet よりOrdering options を検索しTable2より上記Deviceと同じターゲットのRAMサイズを記載(byte)
  • flash_size:
    • Product data sheet よりOrdering options を検索しTable2より上記Deviceと同じターゲットのFlashサイズを記載(byte)
      尚,1KBは1024byteにて計算
  • sector_size:
    • UMから Flash configuration を検索し25.5 General description に「The size of a sector is 1 KB and the size of a page is 64 Byte. One sector contains 16 pages.」と記載があるので,ターゲットのSectorサイズを記載(byte単位).今回の場合は1KBなので1024byte.
    • LPC176xシリーズのセクタサイズは,最初の16セクタが4KB,残りを32KBとしているため一定の値では表せません.これに対応するため特別な値を用意して,プログラム内でその値を検出した際には実際の構成に則した計算を行うようにしています.
  • ram_start_address:
    • UMからUART ISP Write to RAM command もしくは Write to RAM を検索.Example に書いてあるアドレスを記載する.

参考

日本語版だけの(何の役にも立たない)参考情報

Information

何故このプログラムが作られたか.そして何故こんな名前なのか.
こちらを御覧ください →→ イカ醤油ポッポ焼きはイカにして生まれたか(´(ェ)`;

このプログラムを作ってみるきっかけになったツイート.

(´(ェ)`)

Committer:
okano
Date:
Tue Aug 27 05:47:02 2013 +0000
Revision:
12:5a33b5d39792
Parent:
11:8dfc3217d1ca
Child:
13:60995bf8b2c7
Now this can write LPC810!

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okano 11:8dfc3217d1ca 1 /**
okano 11:8dfc3217d1ca 2 * Sample of ISP operation for NXP MCUs
okano 11:8dfc3217d1ca 3 *
okano 11:8dfc3217d1ca 4 * @author Akifumi (Tedd) OKANO, NXP Semiconductors
okano 12:5a33b5d39792 5 * @version 0.5
okano 11:8dfc3217d1ca 6 * @date Aug-2013
okano 11:8dfc3217d1ca 7 */
okano 11:8dfc3217d1ca 8
okano 5:ff30f5b58617 9 #include "mbed.h"
okano 5:ff30f5b58617 10 #include "target_table.h"
okano 0:6baefda2e511 11
okano 2:8d75eb0ecd20 12 BusOut leds( LED4, LED3, LED2, LED1 );
okano 2:8d75eb0ecd20 13 DigitalOut reset_pin( p26 );
okano 2:8d75eb0ecd20 14 DigitalOut isp_pin( p25 );
okano 2:8d75eb0ecd20 15 Serial target ( p28, p27 );
okano 2:8d75eb0ecd20 16 LocalFileSystem local( "local" );
okano 0:6baefda2e511 17
okano 12:5a33b5d39792 18 #define ENTER_TO_ISP_MODE 0
okano 12:5a33b5d39792 19 #define NO_ISP_MODE 1
okano 12:5a33b5d39792 20 #define STR_BUFF_SIZE 64
okano 12:5a33b5d39792 21
okano 1:54e619428ae6 22 #define SOURCE_FILE "/local/bin"
okano 8:b220fadbb3d8 23 #define BAUD_RATE 115200
okano 4:55f1977bd11a 24 //#define BAUD_RATE 57600
okano 8:b220fadbb3d8 25 //#define BAUD_RATE 9600
okano 4:55f1977bd11a 26
okano 8:b220fadbb3d8 27 int error_state = 0;
okano 7:815366f003ee 28
okano 7:815366f003ee 29 int file_size( FILE *fp );
okano 7:815366f003ee 30 void reset_target( int isp_pin_state );
okano 7:815366f003ee 31 int try_and_check( char *command, char *expected_return_str, int mode );
okano 7:815366f003ee 32 int try_and_check2( char *command, char *expected_return_str, int mode );
okano 7:815366f003ee 33 void print_command( char *command );
okano 7:815366f003ee 34 void print_result( int r );
okano 7:815366f003ee 35 char read_byte( void );
okano 7:815366f003ee 36 void erase_sectors( int last_sector );
okano 12:5a33b5d39792 37 int write_uuencoded_data( FILE *fp, int ram_size, int sector_size, unsigned int );
okano 12:5a33b5d39792 38 int write_binary_data( FILE *fp, int ram_size, int sector_size, unsigned int ram_start );
okano 7:815366f003ee 39 void initialize_uue_table( void );
okano 11:8dfc3217d1ca 40 long bin2uue( char *bin, char *str, int size );
okano 12:5a33b5d39792 41 int get_flash_writing_size( int ram_size, unsigned int ram_start );
okano 7:815366f003ee 42 void add_isp_checksum( char *b );
okano 7:815366f003ee 43 void send_RAM_transfer_checksum( int checksum );
okano 7:815366f003ee 44 void put_string( char *s );
okano 12:5a33b5d39792 45 void put_binary( char *b, int size );
okano 7:815366f003ee 46 void get_string( char *s );
okano 7:815366f003ee 47
okano 12:5a33b5d39792 48 #pragma diag_suppress 1293 // surpressing a warning message of "assignment in condition" ;)
okano 12:5a33b5d39792 49
okano 7:815366f003ee 50
okano 7:815366f003ee 51 int main()
okano 7:815366f003ee 52 {
okano 7:815366f003ee 53 FILE *fp;
okano 7:815366f003ee 54 char str_buf0[ STR_BUFF_SIZE ];
okano 7:815366f003ee 55 char str_buf1[ STR_BUFF_SIZE ];
okano 7:815366f003ee 56 int data_size;
okano 7:815366f003ee 57 int last_sector;
okano 7:815366f003ee 58 target_param *tpp;
okano 8:b220fadbb3d8 59
okano 7:815366f003ee 60 printf( "\r\n\r\n\r\nmbed ISP program : programming LPC device from mbed\r\n" );
okano 7:815366f003ee 61
okano 7:815366f003ee 62 target.baud( BAUD_RATE );
okano 8:b220fadbb3d8 63
okano 7:815366f003ee 64 reset_target( ENTER_TO_ISP_MODE );
okano 8:b220fadbb3d8 65
okano 7:815366f003ee 66 try_and_check( "?", "Synchronized", 0 );
okano 8:b220fadbb3d8 67
okano 7:815366f003ee 68 try_and_check2( "Synchronized\r\n", "OK", 0 );
okano 7:815366f003ee 69 try_and_check2( "12000\r\n", "OK", 0 );
okano 7:815366f003ee 70 try_and_check2( "U 23130\r\n", "0", 0 );
okano 7:815366f003ee 71 try_and_check2( "A 0\r\n", "0", 0 );
okano 8:b220fadbb3d8 72
okano 7:815366f003ee 73 try_and_check( "K\r\n", "0", 0 );
okano 7:815366f003ee 74 get_string( str_buf0 );
okano 7:815366f003ee 75 get_string( str_buf1 );
okano 8:b220fadbb3d8 76
okano 7:815366f003ee 77 printf( " result of \"K\" = %s %s\r\n", str_buf0, str_buf1 );
okano 8:b220fadbb3d8 78
okano 7:815366f003ee 79 try_and_check( "J\r\n", "0", 0 );
okano 7:815366f003ee 80 get_string( str_buf0 );
okano 8:b220fadbb3d8 81
okano 7:815366f003ee 82 printf( " result of \"J\" = %s\r\n", str_buf0 );
okano 8:b220fadbb3d8 83
okano 7:815366f003ee 84 tpp = find_target_param( str_buf0 );
okano 8:b220fadbb3d8 85 printf( " target device found : type = \"%s\"\r\n", tpp->type_name );
okano 8:b220fadbb3d8 86 printf( " ID = 0x%08X\r\n", tpp->id );
okano 8:b220fadbb3d8 87 printf( " RAM size = %10d bytes\r\n", tpp->ram_size );
okano 8:b220fadbb3d8 88 printf( " flash size = %10d bytes\r\n", tpp->flash_size );
okano 8:b220fadbb3d8 89
okano 12:5a33b5d39792 90 printf( " opening file: \"%s\"\r\n", SOURCE_FILE );
okano 12:5a33b5d39792 91
okano 12:5a33b5d39792 92 if ( NULL == (fp = fopen( SOURCE_FILE, "rb" )) ) {
okano 12:5a33b5d39792 93 error( "couldn't open source file" );
okano 12:5a33b5d39792 94 return ( 1 );
okano 12:5a33b5d39792 95 }
okano 12:5a33b5d39792 96
okano 12:5a33b5d39792 97 data_size = file_size( fp );
okano 12:5a33b5d39792 98 last_sector = data_size / tpp->sector_size;
okano 12:5a33b5d39792 99
okano 12:5a33b5d39792 100 printf( " data size = %d bytes, it takes %d secotrs in flash area\r\n", data_size, last_sector + 1 );
okano 12:5a33b5d39792 101 printf( " resetting target\r\n" );
okano 12:5a33b5d39792 102
okano 7:815366f003ee 103 erase_sectors( last_sector );
okano 12:5a33b5d39792 104
okano 12:5a33b5d39792 105 if ( tpp->write_type == BINARY )
okano 12:5a33b5d39792 106 write_binary_data( fp, tpp->ram_size, tpp->sector_size, tpp->ram_start_address );
okano 12:5a33b5d39792 107 else // UUENCODE
okano 12:5a33b5d39792 108 write_uuencoded_data( fp, tpp->ram_size, tpp->sector_size, tpp->ram_start_address );
okano 12:5a33b5d39792 109
okano 7:815366f003ee 110 fclose( fp );
okano 8:b220fadbb3d8 111
okano 8:b220fadbb3d8 112 printf( "\r\n %s\r\n\r\n",
okano 8:b220fadbb3d8 113 error_state ?
okano 8:b220fadbb3d8 114 "** The data could not be written :(" :
okano 8:b220fadbb3d8 115 "** The data has been written successflly :)"
okano 8:b220fadbb3d8 116 );
okano 8:b220fadbb3d8 117
okano 7:815366f003ee 118 int i = 0;
okano 8:b220fadbb3d8 119
okano 7:815366f003ee 120 while ( 1 ) {
okano 7:815366f003ee 121 leds = 0x1 << (i++ & 0x3);
okano 7:815366f003ee 122 wait( 0.1 );
okano 7:815366f003ee 123 }
okano 7:815366f003ee 124 }
okano 7:815366f003ee 125
okano 7:815366f003ee 126
okano 7:815366f003ee 127 int file_size( FILE *fp )
okano 7:815366f003ee 128 {
okano 7:815366f003ee 129 int size;
okano 8:b220fadbb3d8 130
okano 7:815366f003ee 131 fseek( fp, 0, SEEK_END ); // seek to end of file
okano 7:815366f003ee 132 size = ftell( fp ); // get current file pointer
okano 7:815366f003ee 133 fseek( fp, 0, SEEK_SET ); // seek back to beginning of file
okano 8:b220fadbb3d8 134
okano 7:815366f003ee 135 return size;
okano 7:815366f003ee 136 }
okano 7:815366f003ee 137
okano 7:815366f003ee 138
okano 7:815366f003ee 139 void reset_target( int isp_pin_state )
okano 7:815366f003ee 140 {
okano 7:815366f003ee 141 reset_pin = 1;
okano 7:815366f003ee 142 isp_pin = 0;
okano 7:815366f003ee 143 wait_ms( 100 );
okano 7:815366f003ee 144 reset_pin = 0;
okano 7:815366f003ee 145 wait_ms( 100 );
okano 7:815366f003ee 146 reset_pin = 1;
okano 7:815366f003ee 147 wait_ms( 100 );
okano 7:815366f003ee 148 }
okano 7:815366f003ee 149
okano 7:815366f003ee 150
okano 7:815366f003ee 151 int try_and_check( char *command, char *expected_return_str, int mode )
okano 7:815366f003ee 152 {
okano 7:815366f003ee 153 char rtn_str[ STR_BUFF_SIZE ];
okano 8:b220fadbb3d8 154 int result = 1;
okano 8:b220fadbb3d8 155
okano 7:815366f003ee 156 print_command( command );
okano 7:815366f003ee 157 put_string( command );
okano 8:b220fadbb3d8 158
okano 7:815366f003ee 159 get_string( rtn_str );
okano 7:815366f003ee 160 print_result( result = strcmp( expected_return_str, rtn_str ) );
okano 8:b220fadbb3d8 161
okano 8:b220fadbb3d8 162 if ( result && !mode )
okano 8:b220fadbb3d8 163 error( "command failed\r\n" );
okano 8:b220fadbb3d8 164
okano 8:b220fadbb3d8 165 error_state |= result;
okano 8:b220fadbb3d8 166
okano 7:815366f003ee 167 return ( result );
okano 7:815366f003ee 168 }
okano 7:815366f003ee 169
okano 7:815366f003ee 170
okano 7:815366f003ee 171 int try_and_check2( char *command, char *expected_return_str, int mode )
okano 7:815366f003ee 172 {
okano 7:815366f003ee 173 char rtn_str[ STR_BUFF_SIZE ];
okano 8:b220fadbb3d8 174 int result = 1;
okano 8:b220fadbb3d8 175
okano 7:815366f003ee 176 print_command( command );
okano 7:815366f003ee 177 put_string( command );
okano 8:b220fadbb3d8 178
okano 7:815366f003ee 179 get_string( rtn_str ); // just readout echoback
okano 7:815366f003ee 180 get_string( rtn_str );
okano 7:815366f003ee 181 print_result( result = strcmp( expected_return_str, rtn_str ) );
okano 8:b220fadbb3d8 182
okano 8:b220fadbb3d8 183 if ( result && !mode )
okano 8:b220fadbb3d8 184 error( "command failed\r\n" );
okano 8:b220fadbb3d8 185
okano 8:b220fadbb3d8 186 error_state |= result;
okano 8:b220fadbb3d8 187
okano 7:815366f003ee 188 return ( result );
okano 7:815366f003ee 189 }
okano 7:815366f003ee 190
okano 7:815366f003ee 191
okano 7:815366f003ee 192 void print_command( char *command )
okano 7:815366f003ee 193 {
okano 7:815366f003ee 194 char s[ STR_BUFF_SIZE ];
okano 7:815366f003ee 195 char *pos;
okano 8:b220fadbb3d8 196
okano 7:815366f003ee 197 strcpy( s, command );
okano 8:b220fadbb3d8 198
okano 7:815366f003ee 199 if ( pos = strchr( s, '\r' ) )
okano 7:815366f003ee 200 *pos = '\0';
okano 8:b220fadbb3d8 201
okano 7:815366f003ee 202 if ( pos = strchr( s, '\n' ) )
okano 7:815366f003ee 203 *pos = '\0';
okano 8:b220fadbb3d8 204
okano 7:815366f003ee 205 printf( " command-\"%s\" : ", s );
okano 7:815366f003ee 206 }
okano 7:815366f003ee 207
okano 7:815366f003ee 208
okano 7:815366f003ee 209 void print_result( int r )
okano 7:815366f003ee 210 {
okano 7:815366f003ee 211 printf( "%s\r\n", r ? "Fail" : "Pass" );
okano 7:815366f003ee 212 }
okano 7:815366f003ee 213
okano 7:815366f003ee 214
okano 7:815366f003ee 215 char read_byte( void )
okano 7:815366f003ee 216 {
okano 7:815366f003ee 217 while ( !target.readable() )
okano 7:815366f003ee 218 ;
okano 8:b220fadbb3d8 219
okano 7:815366f003ee 220 return ( target.getc() );
okano 7:815366f003ee 221 }
okano 7:815366f003ee 222
okano 7:815366f003ee 223
okano 7:815366f003ee 224 void erase_sectors( int last_sector )
okano 7:815366f003ee 225 {
okano 7:815366f003ee 226 char command_str[ STR_BUFF_SIZE ];
okano 8:b220fadbb3d8 227
okano 7:815366f003ee 228 sprintf( command_str, "P 0 %d\r\n", last_sector );
okano 7:815366f003ee 229 try_and_check( command_str, "0", 0 );
okano 8:b220fadbb3d8 230
okano 7:815366f003ee 231 *(command_str) = 'E';
okano 7:815366f003ee 232 try_and_check( command_str, "0", 0 );
okano 7:815366f003ee 233 }
okano 7:815366f003ee 234
okano 12:5a33b5d39792 235 #define BYTES_PER_LINE 45
okano 12:5a33b5d39792 236 char uue_table[ 64 ];
okano 7:815366f003ee 237
okano 12:5a33b5d39792 238 int write_uuencoded_data( FILE *fp, int ram_size, int sector_size, unsigned int ram_start )
okano 7:815366f003ee 239 {
okano 7:815366f003ee 240 char command_str[ STR_BUFF_SIZE ];
okano 7:815366f003ee 241 long checksum = 0;
okano 7:815366f003ee 242 int total_size = 0;
okano 7:815366f003ee 243 int size;
okano 8:b220fadbb3d8 244
okano 7:815366f003ee 245 int flash_writing_size;
okano 7:815366f003ee 246 int lines_per_transfer;
okano 7:815366f003ee 247 int transfer_size;
okano 8:b220fadbb3d8 248
okano 12:5a33b5d39792 249 char *b;
okano 12:5a33b5d39792 250
okano 7:815366f003ee 251 initialize_uue_table();
okano 8:b220fadbb3d8 252
okano 12:5a33b5d39792 253 flash_writing_size = get_flash_writing_size( ram_size, ram_start );
okano 11:8dfc3217d1ca 254 lines_per_transfer = ((flash_writing_size / BYTES_PER_LINE) + 1);
okano 11:8dfc3217d1ca 255 transfer_size = (((flash_writing_size + 11) / 12) * 12);
okano 8:b220fadbb3d8 256
okano 7:815366f003ee 257 // char b[ transfer_size ]; // this can be done in mbed-compiler. but I should do it in common way
okano 8:b220fadbb3d8 258
okano 7:815366f003ee 259 if ( NULL == (b = (char *)malloc( transfer_size * sizeof( char ) )) )
okano 7:815366f003ee 260 error( "malloc error happened\r\n" );
okano 8:b220fadbb3d8 261
okano 7:815366f003ee 262 for ( int i = flash_writing_size; i < transfer_size; i++ )
okano 7:815366f003ee 263 b[ i ] = 0; // this is not neccesary but just stuffing stuffing bytes
okano 8:b220fadbb3d8 264
okano 7:815366f003ee 265 while ( size = fread( b, sizeof( char ), flash_writing_size, fp ) ) {
okano 8:b220fadbb3d8 266
okano 7:815366f003ee 267 if ( !total_size ) {
okano 7:815366f003ee 268 // overwriting 4 bytes data for address=0x1C
okano 7:815366f003ee 269 // there is a slot for checksum that is checked in (target's) boot process
okano 7:815366f003ee 270 add_isp_checksum( b );
okano 7:815366f003ee 271 }
okano 8:b220fadbb3d8 272
okano 12:5a33b5d39792 273 sprintf( command_str, "W %ld %ld\r\n", ram_start, transfer_size );
okano 7:815366f003ee 274 try_and_check( command_str, "0", 0 );
okano 8:b220fadbb3d8 275
okano 7:815366f003ee 276 for ( int i = 0; i < lines_per_transfer; i++ ) {
okano 12:5a33b5d39792 277
okano 11:8dfc3217d1ca 278 checksum += bin2uue( b + (i * BYTES_PER_LINE), command_str, i == (lines_per_transfer - 1) ? (transfer_size % BYTES_PER_LINE) : BYTES_PER_LINE );
okano 8:b220fadbb3d8 279
okano 12:5a33b5d39792 280 // printf( " data -- %02d %s\r", i, command_str );
okano 8:b220fadbb3d8 281
okano 7:815366f003ee 282 put_string( command_str );
okano 8:b220fadbb3d8 283
okano 7:815366f003ee 284 if ( !((i + 1) % 20) ) {
okano 7:815366f003ee 285 send_RAM_transfer_checksum( checksum );
okano 7:815366f003ee 286 checksum = 0;
okano 7:815366f003ee 287 }
okano 7:815366f003ee 288 }
okano 8:b220fadbb3d8 289
okano 7:815366f003ee 290 send_RAM_transfer_checksum( checksum );
okano 7:815366f003ee 291 checksum = 0;
okano 8:b220fadbb3d8 292
okano 12:5a33b5d39792 293 sprintf( command_str, "P %d %d\r\n", total_size / sector_size, total_size / sector_size );
okano 7:815366f003ee 294 try_and_check( command_str, "0", 0 );
okano 8:b220fadbb3d8 295
okano 12:5a33b5d39792 296 sprintf( command_str, "C %d %d %d\r\n", total_size, ram_start, flash_writing_size );
okano 7:815366f003ee 297 try_and_check( command_str, "0", 0 );
okano 8:b220fadbb3d8 298
okano 7:815366f003ee 299 total_size += size;
okano 7:815366f003ee 300 }
okano 8:b220fadbb3d8 301
okano 7:815366f003ee 302 try_and_check( "G 0 T\r\n", "0", 0 );
okano 7:815366f003ee 303 free( b );
okano 8:b220fadbb3d8 304
okano 12:5a33b5d39792 305 return ( total_size );
okano 7:815366f003ee 306 }
okano 7:815366f003ee 307
okano 7:815366f003ee 308
okano 12:5a33b5d39792 309 int write_binary_data( FILE *fp, int ram_size, int sector_size, unsigned int ram_start )
okano 12:5a33b5d39792 310 {
okano 12:5a33b5d39792 311 char command_str[ STR_BUFF_SIZE ];
okano 12:5a33b5d39792 312 int total_size = 0;
okano 12:5a33b5d39792 313 int size;
okano 12:5a33b5d39792 314 int flash_writing_size;
okano 12:5a33b5d39792 315 char *b;
okano 12:5a33b5d39792 316
okano 12:5a33b5d39792 317 flash_writing_size = 256;
okano 12:5a33b5d39792 318
okano 12:5a33b5d39792 319 if ( NULL == (b = (char *)malloc( flash_writing_size * sizeof( char ) )) )
okano 12:5a33b5d39792 320 error( "malloc error happened\r\n" );
okano 12:5a33b5d39792 321
okano 12:5a33b5d39792 322 while ( size = fread( b, sizeof( char ), flash_writing_size, fp ) ) {
okano 12:5a33b5d39792 323
okano 12:5a33b5d39792 324 if ( !total_size ) {
okano 12:5a33b5d39792 325 // overwriting 4 bytes data for address=0x1C
okano 12:5a33b5d39792 326 // there is a slot for checksum that is checked in (target's) boot process
okano 12:5a33b5d39792 327 add_isp_checksum( b );
okano 12:5a33b5d39792 328 }
okano 12:5a33b5d39792 329
okano 12:5a33b5d39792 330 sprintf( command_str, "W %ld %ld\r\n", ram_start, flash_writing_size );
okano 12:5a33b5d39792 331 try_and_check( command_str, "0", 0 );
okano 12:5a33b5d39792 332
okano 12:5a33b5d39792 333 put_binary( b, flash_writing_size );
okano 12:5a33b5d39792 334 put_string( "\r\n" );
okano 12:5a33b5d39792 335
okano 12:5a33b5d39792 336 sprintf( command_str, "P %d %d\r\n", total_size / sector_size, total_size / sector_size );
okano 12:5a33b5d39792 337 try_and_check( command_str, "0", 0 );
okano 12:5a33b5d39792 338
okano 12:5a33b5d39792 339 sprintf( command_str, "C %d %d %d\r\n", total_size, ram_start, flash_writing_size );
okano 12:5a33b5d39792 340 try_and_check( command_str, "0", 0 );
okano 12:5a33b5d39792 341
okano 12:5a33b5d39792 342 total_size += size;
okano 12:5a33b5d39792 343 printf( " total %d bytes transferred\r", total_size );
okano 12:5a33b5d39792 344
okano 12:5a33b5d39792 345 }
okano 12:5a33b5d39792 346
okano 12:5a33b5d39792 347 free( b );
okano 12:5a33b5d39792 348
okano 12:5a33b5d39792 349 return ( total_size );
okano 12:5a33b5d39792 350 }
okano 12:5a33b5d39792 351
okano 7:815366f003ee 352 void initialize_uue_table( void )
okano 7:815366f003ee 353 {
okano 7:815366f003ee 354 int i;
okano 8:b220fadbb3d8 355
okano 7:815366f003ee 356 uue_table[0] = 0x60; // 0x20 is translated to 0x60 !
okano 8:b220fadbb3d8 357
okano 7:815366f003ee 358 for (i = 1; i < 64; i++) {
okano 7:815366f003ee 359 uue_table[i] = (char)(0x20 + i);
okano 7:815366f003ee 360 }
okano 7:815366f003ee 361 }
okano 7:815366f003ee 362
okano 7:815366f003ee 363
okano 11:8dfc3217d1ca 364 long bin2uue( char *bin, char *str, int size )
okano 7:815366f003ee 365 {
okano 7:815366f003ee 366 unsigned long v;
okano 7:815366f003ee 367 long checksum = 0;
okano 7:815366f003ee 368 int strpos = 0;
okano 8:b220fadbb3d8 369
okano 11:8dfc3217d1ca 370 *(str + strpos++) = ' ' + size;
okano 8:b220fadbb3d8 371
okano 11:8dfc3217d1ca 372 for ( int i = 0; i < size; i += 3 ) {
okano 7:815366f003ee 373 checksum += *(bin + i + 0) + *(bin + i + 1) + *(bin + i + 2);
okano 7:815366f003ee 374 v = (*(bin + i + 0) << 16) | (*(bin + i + 1) << 8) | (*(bin + i + 2) << 0);
okano 7:815366f003ee 375 *(str + strpos++) = uue_table[ (v >> 18) & 0x3F ];
okano 7:815366f003ee 376 *(str + strpos++) = uue_table[ (v >> 12) & 0x3F ];
okano 7:815366f003ee 377 *(str + strpos++) = uue_table[ (v >> 6) & 0x3F ];
okano 7:815366f003ee 378 *(str + strpos++) = uue_table[ (v >> 0) & 0x3F ];
okano 7:815366f003ee 379 }
okano 7:815366f003ee 380 *(str + strpos++) = '\n';
okano 7:815366f003ee 381 *(str + strpos++) = '\0';
okano 8:b220fadbb3d8 382
okano 7:815366f003ee 383 return checksum;
okano 7:815366f003ee 384 }
okano 6:0ae6fe8c8512 385
okano 6:0ae6fe8c8512 386
okano 12:5a33b5d39792 387 int get_flash_writing_size( int ram_size, unsigned int ram_start )
okano 6:0ae6fe8c8512 388 {
okano 6:0ae6fe8c8512 389 int flash_writing_size[] = {
okano 6:0ae6fe8c8512 390 4096,
okano 6:0ae6fe8c8512 391 1024,
okano 6:0ae6fe8c8512 392 512,
okano 6:0ae6fe8c8512 393 256
okano 6:0ae6fe8c8512 394 };
okano 6:0ae6fe8c8512 395 int available_size;
okano 6:0ae6fe8c8512 396 int i;
okano 8:b220fadbb3d8 397
okano 12:5a33b5d39792 398 available_size = ram_size - (ram_start & 0xFFFF);
okano 8:b220fadbb3d8 399
okano 6:0ae6fe8c8512 400 for ( i = 0; i < sizeof( flash_writing_size ) / sizeof( int ); i++ ) {
okano 6:0ae6fe8c8512 401 if ( flash_writing_size[ i ] < available_size )
okano 6:0ae6fe8c8512 402 break;
okano 6:0ae6fe8c8512 403 }
okano 8:b220fadbb3d8 404
okano 6:0ae6fe8c8512 405 return ( flash_writing_size[ i ] );
okano 6:0ae6fe8c8512 406 }
okano 4:55f1977bd11a 407
okano 4:55f1977bd11a 408
okano 1:54e619428ae6 409 void add_isp_checksum( char *b )
okano 1:54e619428ae6 410 {
okano 1:54e619428ae6 411 // see http://www.lpcware.com/content/nxpfile/lpc177x8x-checksum-insertion-program
okano 8:b220fadbb3d8 412
okano 1:54e619428ae6 413 unsigned int *p;
okano 1:54e619428ae6 414 unsigned int cksum = 0;
okano 8:b220fadbb3d8 415
okano 1:54e619428ae6 416 p = (unsigned int *)b;
okano 8:b220fadbb3d8 417
okano 1:54e619428ae6 418 for ( int i = 0; i < 7; i++ ) {
okano 1:54e619428ae6 419 cksum += *p++;
okano 1:54e619428ae6 420 }
okano 8:b220fadbb3d8 421
okano 1:54e619428ae6 422 printf( " -- value at checksum slot : 0x%08X\r\n", *p );
okano 8:b220fadbb3d8 423
okano 1:54e619428ae6 424 *p = 0xFFFFFFFF - cksum + 1;
okano 1:54e619428ae6 425 printf( " -- calculated checksum : 0x%08X\r\n", *p );
okano 8:b220fadbb3d8 426
okano 1:54e619428ae6 427 printf( " new checksum will be used to program flash\r\n" );
okano 1:54e619428ae6 428 }
okano 1:54e619428ae6 429
okano 1:54e619428ae6 430
okano 4:55f1977bd11a 431 void send_RAM_transfer_checksum( int checksum )
okano 4:55f1977bd11a 432 {
okano 4:55f1977bd11a 433 char command[ 16 ];
okano 8:b220fadbb3d8 434
okano 4:55f1977bd11a 435 sprintf( command, "%d\n", checksum );
okano 4:55f1977bd11a 436 try_and_check( command, "OK", 0 );
okano 4:55f1977bd11a 437 }
okano 4:55f1977bd11a 438
okano 0:6baefda2e511 439
okano 0:6baefda2e511 440 void put_string( char *s )
okano 0:6baefda2e511 441 {
okano 2:8d75eb0ecd20 442 char c;
okano 2:8d75eb0ecd20 443 static int i = 0;
okano 8:b220fadbb3d8 444
okano 3:3c380e643e74 445 while ( c = *s++ ) {
okano 0:6baefda2e511 446 target.putc( c );
okano 2:8d75eb0ecd20 447 leds = i++ & 0x1;
okano 2:8d75eb0ecd20 448 }
okano 0:6baefda2e511 449 }
okano 0:6baefda2e511 450
okano 7:815366f003ee 451
okano 12:5a33b5d39792 452 void put_binary( char *b, int size )
okano 12:5a33b5d39792 453 {
okano 12:5a33b5d39792 454 for ( int i = 0; i < size; i++ )
okano 12:5a33b5d39792 455 target.putc( *b++ );
okano 12:5a33b5d39792 456 }
okano 12:5a33b5d39792 457
okano 12:5a33b5d39792 458
okano 9:ca4c9a2ac8e1 459 Timeout timeout;
okano 9:ca4c9a2ac8e1 460
okano 9:ca4c9a2ac8e1 461 int timeout_flag = 0;
okano 9:ca4c9a2ac8e1 462
okano 9:ca4c9a2ac8e1 463 void set_flag()
okano 9:ca4c9a2ac8e1 464 {
okano 9:ca4c9a2ac8e1 465 timeout_flag = 1;
okano 9:ca4c9a2ac8e1 466 }
okano 9:ca4c9a2ac8e1 467
okano 9:ca4c9a2ac8e1 468
okano 0:6baefda2e511 469 void get_string( char *s )
okano 0:6baefda2e511 470 {
okano 0:6baefda2e511 471 int i = 0;
okano 0:6baefda2e511 472 char c = 0;
okano 9:ca4c9a2ac8e1 473 timeout_flag = 0;
okano 9:ca4c9a2ac8e1 474
okano 9:ca4c9a2ac8e1 475 timeout.attach( &set_flag, 1 );
okano 8:b220fadbb3d8 476
okano 0:6baefda2e511 477 do {
okano 0:6baefda2e511 478 do {
okano 0:6baefda2e511 479 if ( target.readable() ) {
okano 0:6baefda2e511 480 c = target.getc();
okano 8:b220fadbb3d8 481
okano 0:6baefda2e511 482 if ( ( c == '\n') || (c == '\r') )
okano 0:6baefda2e511 483 break;
okano 8:b220fadbb3d8 484
okano 0:6baefda2e511 485 *s++ = c;
okano 0:6baefda2e511 486 i++;
okano 0:6baefda2e511 487 }
okano 9:ca4c9a2ac8e1 488
okano 9:ca4c9a2ac8e1 489 if ( timeout_flag )
okano 9:ca4c9a2ac8e1 490 return;
okano 0:6baefda2e511 491 } while ( 1 );
okano 0:6baefda2e511 492 } while ( !i );
okano 8:b220fadbb3d8 493
okano 0:6baefda2e511 494 *s = '\0';
okano 0:6baefda2e511 495 }
okano 9:ca4c9a2ac8e1 496