目次: OpenOCD
フラッシュの書き込みは、ヘルパープログラムを使うタイプ(上記で追いかけた方)と、SPIを直接制御する方があります。高速に書き込めるのはヘルパープログラムを使うタイプですが、わかりやすいのはSPIを直接制御するタイプです。そちらも見てみましょう。
// openocd/src/flash/nor/fespi.c
static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
...
struct working_area *algorithm_wa;
if (target_alloc_working_area(target, sizeof(algorithm_bin),
&algorithm_wa) != ERROR_OK) {
LOG_WARNING("Couldn't allocate %zd-byte working area.",
sizeof(algorithm_bin));
algorithm_wa = NULL;
} else {
retval = target_write_buffer(target, algorithm_wa->address,
sizeof(algorithm_bin), algorithm_bin); //★ヘルパープログラム本体algorithm_binをターゲットのメモリに書く
if (retval != ERROR_OK) {
LOG_ERROR("Failed to write code to " TARGET_ADDR_FMT ": %d",
algorithm_wa->address, retval);
target_free_working_area(target, algorithm_wa);
algorithm_wa = NULL;
}
}
...
page_offset = offset % page_size;
/* central part, aligned words */
while (count > 0) {
/* clip block at page boundary */
if (page_offset + count > page_size)
cur_count = page_size - page_offset;
else
cur_count = count;
if (algorithm_wa)
retval = steps_add_buffer_write(bank, as, buffer, offset, cur_count); //★バッファに書き込むデータを追加する(通常はこちら)
else
retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count); //★JTAGからSPIを直接操作して書き込むモード(遅い)
if (retval != ERROR_OK)
goto err;
page_offset = 0;
buffer += cur_count;
offset += cur_count;
count -= cur_count;
}
//★ヘルパープログラムに書き込むデータを全部渡し、フラッシュに書き込みしてもらう
if (algorithm_wa)
retval = steps_execute(as, bank, algorithm_wa, data_wa);
...
ここまでは前回と同じです。前回はsteps_add_buffer_write() とsteps_execute() が活躍しましたが、今回はslow_fespi_write_buffer() の方を見ます。
static int slow_fespi_write_buffer(struct flash_bank *bank,
const uint8_t *buffer, uint32_t offset, uint32_t len)
{
uint32_t ii;
if (offset & 0xFF000000) {
LOG_ERROR("FESPI interface does not support greater than 3B addressing, can't write to offset 0x%" PRIx32,
offset);
return ERROR_FAIL;
}
/* TODO!!! assert that len < page size */
fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
fespi_txwm_wait(bank);
if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK) //★CE# 信号をLowにする(負論理、処理の開始を示す)
return ERROR_FAIL;
fespi_tx(bank, SPIFLASH_PAGE_PROGRAM); //★PPコマンド = 0x02
fespi_tx(bank, offset >> 16); //★アドレス
fespi_tx(bank, offset >> 8);
fespi_tx(bank, offset);
for (ii = 0; ii < len; ii++) //★データ
fespi_tx(bank, buffer[ii]);
fespi_txwm_wait(bank); //★送信し終わるまで待つ
if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK) //★CE# 信号をHighにする(負論理、処理の終了を示す)
return ERROR_FAIL;
keep_alive();
return ERROR_OK;
}
// openocd/src/flash/nor/spi.h
/* SPI Flash Commands */
#define SPIFLASH_READ_ID 0x9F /* Read Flash Identification */
#define SPIFLASH_READ_MID 0xAF /* Read Flash Identification, multi-io */
#define SPIFLASH_READ_STATUS 0x05 /* Read Status Register */
#define SPIFLASH_WRITE_ENABLE 0x06 /* Write Enable */
#define SPIFLASH_PAGE_PROGRAM 0x02 /* Page Program */ //★コマンドはこれ
...
コマンド、データ、待機、たったこれだけです。前回はヘルパープログラムの制御などが出てきて複雑でしたが、実はSPI Flashの制御だけ見ると非常にシンプルです。
< | 2021 | > | ||||
<< | < | 07 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | - | - | 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
合計:
本日:
管理者: Katsuhiro Suzuki(katsuhiro( a t )katsuster.net)
This is Simple Diary 1.0
Copyright(C) Katsuhiro Suzuki 2006-2023.
Powered by PHP 8.2.18.
using GD 2.3.3(png support.)