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:
Mon Sep 09 15:10:50 2013 +0000
Revision:
18:b401da200216
Parent:
17:339f40a14f67
Child:
19:7a7381e78025
some comments edited

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