d2xx と libftdi1 の共有
d2xx のほう.
static int x_ft_write(void *tt, uint8_t *data, int length) { struct d2xx *t = tt; DWORD rc; FT_STATUS s = FT_Write(t->h, data, length, &rc); assert(s == FT_OK); return rc; } static int x_ft_read(void *tt, uint8_t *data, int length) { struct d2xx *t = tt; DWORD rc; FT_STATUS s = FT_Read(t->h, data, length, &rc); assert(s == FT_OK); return rc; } static void x_ft_close(void *tt) { struct d2xx *t = tt; FT_STATUS s = FT_SetBitMode(t->h, 0, FT_BITMODE_RESET); assert(s == FT_OK); FT_Close(t->h); } static const struct mpsse_driver d2xx_driver = { x_ft_write, x_ft_read, x_ft_close };
libftdi1 のほう.
static int mou_write(void *tt, uint8_t *data, int length) { struct ftdi1 *t = tt; return ftdi_write_data(&t->mpsse_ftdic, data, length); } static int mou_read(void *tt, uint8_t *data, int length) { struct ftdi1 *t = tt; return ftdi_read_data(&t->mpsse_ftdic, data, length); } static void mou_close(void *tt) { struct ftdi1 *t = tt; if(t->mpsse_ftdic_open){ if(t->mpsse_ftdic_latency_set){ ftdi_set_latency_timer(&t->mpsse_ftdic, t->mpsse_ftdi_latency); } ftdi_disable_bitbang(&t->mpsse_ftdic); ftdi_usb_close(&t->mpsse_ftdic); } ftdi_deinit(&t->mpsse_ftdic); } static const struct mpsse_driver ftdi1_driver = { mou_write, mou_read, mou_close };
こんな感じにクラスもどきを作って, 切り替える.
これの対応自体は大したことがないが C 故に void * を使うのでエラーチェックが雑で原因究明に困るとか、グローバル変数をローカル変数にかえる(必須ではないがやりたくなる)のが手間. void * は &data と書くべきところを data としていたので動かない系統のミスが多すぎるし予防できない.
flash_wait() の修正
verbose の都合なのか status register を待ち時間をいれて 2 度確認する仕様になってたので書き直した.
static void flash_wait(struct mpsse *t, const useconds_t first, const useconds_t every) { if(verbose){ fprintf(stderr, "waiting.."); } useconds_t waitus = first; uint8_t data[2]; do{ usleep(waitus); waitus = every; data[0] = FC_RSR1; data[1] = 0; flash_xfer(t, data, sizeof(data)); }while(data[1] & 1); if(verbose){ fprintf(stderr, "R\n"); fflush(stderr); } }
戻り値 void, 引数 void の関数とか while(1) がやたらと多いソースはもしかするとダメなんじゃと予感がするがほぼ的中する.
flash_read() の分離
他に flash_read_status とかがあったので prefix を flash_read_data に改名. flash_read() のなかで [CS=L, コマンド発行, data 取得, CS=H ]の流れを毎回やっていたので flash_read_data_start() で [CS=L, コマンド発行], flash_read_data_continue() で [data 取得] に分離して、ループの内部での無駄な手続きを削除.
妙に長い待機時間を削減
ループの外とはいえ 200ms 待つ処理がコピペされてたので技術文書と確認. iceprog も C_RESET_B = 0 の期間にすべて転送していているので、規定時間というのが場当たり的対応になっている.
それでも 200 ms は明らかに長いのでこちらも場当たり的に削減.
根本的には時間が明言されている C_RESET_B = 0 をして SS = 0 で C_RESET_B = 1 にして slave mode に入ることが求められる. これの実装はソフトとハードも後回し.
総括
これらの対応で前回 6.9 秒かかった処理が 4.2 秒にまで縮んだ. これでとりあえず満足したので本来の目的に戻る.