090613

|


Interface 2009/5月号の付録基板の続き。
昨日、ユーザ定義セクション(.vector)を
	 .vector :
	 {
		*(.vector)
	 } > vectors
としてLOADが立たないのは、ソース側で
	.section	.vector
としていたためだった。
	.section	.vector, "ax"
	.align	2
のように"a"でallocateを明示的に立てないとだめ。"x"はテキスト。これはな
くてもいい。
LPC2388のブートローダ(ISP)をNetBSDのtipから操作してみました。なんとかフ ラッシュの書き込みまでできるのを確認しました。
uslsa0 at uhub0 port 3
uslsa0: Silicon Labs CP2102 USB to UART Bridge Controller, rev 1.10/1.00, addr 4
ucom0 at uslsa0: Silicon Labs CP210x

/etc/remote

umon:dv=/dev/dtyU0:br#115200:pa=none:dc:

$ tip umon
connected
Synchronized
OKnchronized

'?'を叩くと、自動ボーレート合わせこみが完了しSynchronizedと返事が
来る。そこ後ホスト側からもSynchronizedと叩く。OKと返事が来る。
周波数を設定するために12000と叩く(12MHz)


'K'コマンド(Read Boot Code version number)
0	CMD_SUCCESS
3	Major
3	Minor

'J'コマンド(Read Part Identification number)
0		CMD_SUCCESS
402718517	Table 29.543 LPC2300 part Identification numbers (LPC2388)


'U'コマンド (Unlock)
12	PARAM_ERROR

U 23130
0	CMD_SUCCESS

'R' (Read Memory)
R 0 64

M&$"?Y1!0G^4`8)3E!F`%X`!@A.4$\!_E0.#_?_^___\`@/\_````````````
3````````````````````````````
4797

R 0 32

0 0 32
@&$"?Y1!0G^4`8)3E!F`%X`!@A.4$\!_E0.#_?_^_____
4351

この後ホスト側からOKを返してコマンド終了。

0 0 4
$&$"?Y>7E
476

$&$"?Y>7Eをuudecodeすると、0x18,0x40,0x9f,0xe5。0x18+0x40+0x9f+0xe5=476

例えば0x0からを読み出し、uudecodeして
arm-elf-objcopy -I binary -O elf32-littlearm test.bin test.elf
arm-elf-objdump -m arm -D test.elf
したもの。arm-elf-objdumpのバグで一度ELFにしないとバイナリから直接ディ
スアセンブルできない。

00000000 <_binary_test_bin_start>:
   0:	e59f4018 	ldr	r4, [pc, #24]	; 20 <_binary_test_bin_start+0x20> r4 = 0x3fff8000 PARTCFG REGISTER
   4:	e59f5010 	ldr	r5, [pc, #16]	; 1c <_binary_test_bin_start+0x1c> r5 = ~0x4000
   8:	e5946000 	ldr	r6, [r4]	; r6 = *((int32_t *)0x3fff8000)
   c:	e0056006 	and	r6, r5, r6	; r6 &= ~0x4000
  10:	e5846000 	str	r6, [r4]	; *((int32_t *)0x3fff8000) = r6
  14:	e51ff004 	ldr	pc, [pc, #-4]	; 18 <_binary_test_bin_start+0x18> jump to 0x7fffe040
  18:	7fffe040 	svcvc	0x00ffe040
  1c:	ffffbfff 	undefined instruction 0xffffbfff
  20:	3fff8000 	svccc	0x00ff8000
	...
  40:	ffffffff 	undefined instruction 0xffffffff
PARTCFG レジスタの14bitを落としてからISPコードを実行する。PARTCFGレジスタの
詳細は不明。



'G' コマンド
G 0 A
で0x0から実行。この場合ISPが最初から動くことになる。


ISPはRAM 0x40000120-0x400001ffまでを使う、スタックはRAM top -32から。最
大256byte使う。

ISPとのデータのやりとりはuuencodeされたもので受けわたしする。rawdata
45byte づつなので、通常のuuencodeでよい。異なるポイントは20ラインごとに
チェックサムを送ること。最後の0byteラインを入れない。

通常のuuencode(/usr/bin/uuencode)
JH.,`((/E_SW@XS\Q0^(`(*#C`""#Y?\]X.,O,4/B`""@XP`@@^7^___J
` ←これはこのラインは0ということ。uudecodeの場合これを終端と認識する。
end

の所を

JH.,`((/E_SW@XS\Q0^(`(*#C`""#Y?\]X.,O,4/B`""@XP`@@^7^___J
41994 ←チェックサムを入れる。

のようにしないといけない。

これらを使ってバイナリをRAMにロードする手順は、
まず、JP2をショートしてリセットをかける。
tipで接続。
以下、ホストから叩く順
?			自動合わせこみに失敗したらもう一度リセットから。通常1個叩けばよい。
Synchronized		返答
12000			初期状態のクロックを設定これは12MHzに設定。
A 0			エコーバックするとISP側の処理が間にあわないのでエコーオフ
W 1073742336 852	0x40000200(内蔵SRAM)から852byte(これはraw dataの量)書き込み。0x40000000-0x400001ffまではISPが使っているから。
~> test.uu		送りこみ。OKが出れば完了。失敗するとRESENDと表示される。
A 1			エコーバックするように戻す
U 23130			アンロック。G コマンド、及びフラッシュロムの書き込みコマンドはロックがかかっているので。
P 0 0			フラッシュ0セクタを準備
E 0 0			フラッシュ0セクタを消去
P 0 0			フラッシュ0セクタを準備
C 0 1073742336 1024	フラッシュ0セクタに0x40000200(内蔵SRAM)から1024byte書き込み
G 1073742336 A		0x40000200にジャンプ (確認。しなくともよい)

これでRAM上に乗せたプログラムが実行される。ARMの分岐はPC相対なので場所
はどこでも動く。RAMとROMで読み出しスピードが違うのでディレイのループは
ROMの10倍以上とる。ファイルの転送は115200bpsで大丈夫。エコーバックする
と9600bpsでも失敗する。

これでJP2をオープンにしてリセットをかけてLEDが点滅すれば成功。点滅せず、
tipから'?'を叩いてSynchronizedと出れば、ベクターのチェックサムが間違っ
ていてISPモードに落ちたということ。このチェックサムは

	.section	.vector, "ax"
	.align	2
	.global	vector_table
vector_table:
	b	func0		// 0xea00007e
	.long	0x00
	.long	0x00
	.long	0x00
	.long	0x00
	.long	0x69e23484	//チェックサムの調整部分。
//	.long	0x07
	.long	0xac1dcafe
	.long	0x00

0xea00007e+0xac1dcafe + 0x69e23484 = 0になるようにする。

0xea+0x7e+0xac+0x1d+0xca+0xfe + 0x7 = 0x400ではだめ。

Synchronized
OKnchronized
OK000
0 0
0
~>Local file name? test.uu
20 lines transferred in 0 seconds 
!
OK
0
0 23130
0 1073742336 A

フラッシュロムのセクタサイズはアドレスによって異なる。Section 29,
Table 527 参照。セクタ0は4KB。書き込みの際は4KB書かなくてもよい。


バイナリイメージからのuuencodeには
http://www.wotsit.org/download.asp?f=uuencode&sc=298186266
のサンプルを改造して、20ラインごとにチェックサムを出力し、最後の0byteを
出力しないようにした。

/*
 * uuencode.c -
 *  Simple uuencode utility
 *  Jim Cameron, 1997
 */

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>

#define	MAX_LINELEN 45
#define	ENCODE_BYTE(b) (((b) == 0) ? 0x60 : ((b) + 0x20))

int
main (int argc, char *argv[])
{
  FILE *infile	= NULL;
  FILE *outfile = NULL;
  int linelen;
  int linecnt;
  uint8_t inbuf[MAX_LINELEN];
  uint8_t *inbytep;
  char outbuf[5];
  int i;

  if (argc != 3)
    {
      fprintf (stderr, "Syntax: uuencode <infile> <outfile>\n");
      exit (1);
    }

  /* Try and open the input file (binary) */

  infile = fopen (argv[1], "rb");
  if (infile == NULL)
    {
      fprintf (stderr, "uuencode: Couldn't open input file %s\n", argv[1]);
      exit (1);
    }

  /* Try and open the output file (text) */

  outfile = fopen (argv[2], "wt");
  if (outfile == NULL)
    {
      fprintf (stderr, "uuencode: Couldn't open output file %s\n", argv[2]);
      exit (1);
    }

  int checksum, nline;
  checksum = 0;
  nline = 0;
  do
    {
      /* Read a line from input file */
      linelen = fread (inbuf, 1, MAX_LINELEN, infile);
      if (!linelen)
	break;
      for (i = 0; i < linelen; i++)
	checksum += inbuf[i];

      /* Write the line length byte */
      fputc (ENCODE_BYTE (linelen), outfile);

      /* Encode the line */
      for (linecnt = linelen, inbytep = inbuf; linecnt > 0;
	   linecnt -= 3, inbytep += 3)
	{
	  /* Encode 3 bytes from the input buffer */
	  outbuf[0] = ENCODE_BYTE ((inbytep[0] & 0xFC) >> 2);
	  outbuf[1] = ENCODE_BYTE (((inbytep[0] & 0x03) << 4) +
				   ((inbytep[1] & 0xF0) >> 4));
	  outbuf[2] = ENCODE_BYTE (((inbytep[1] & 0x0F) << 2) +
				   ((inbytep[2] & 0xC0) >> 6));
	  outbuf[3] = ENCODE_BYTE (inbytep[2] & 0x3F);
	  outbuf[4] = '\0';

	  /* Write the 4 encoded bytes to the file */
	  fprintf (outfile, "%s", outbuf);
	}

      fprintf (outfile, "\n");
      if (++nline == 20)
	{
	  fprintf (outfile, "%d\n", checksum);
	  nline = checksum = 0;
	}
    }
  while (linelen != 0);
  if (nline)
    fprintf (outfile, "%d\n", checksum);

  fclose (infile);
  fclose (outfile);

  return 0;

}