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:
Sun Aug 25 02:54:53 2013 +0000
Revision:
6:0ae6fe8c8512
Parent:
5:ff30f5b58617
Child:
7:815366f003ee
transfer size adjustment can be done automatically by detecting "part-ID".

Who changed what in which revision?

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