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 03:09:07 2013 +0000
Revision:
11:8dfc3217d1ca
Parent:
10:90bd46dadeb4
Child:
12:5a33b5d39792
more flexible transfer size

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