最新の fsbl で Linux が起動しない理由を調べる のバックアップの現在との差分(No.2)

更新


  • 追加された行はこの色です。
  • 削除された行はこの色です。
[[公開メモ]]

* Petalinux 2016.4 の生成する fsbl が動作しない [#de4f661e]

[[電気回路/zynq/Petalinux のビルド#h00d6c35]] で見たとおり、
何のメッセージも出ず固まってしまいます。。。

z-turn 付属の dvd にあった mys-xc7z020-trd というサンプルプロジェクト
からビルドした fsbl ではうまく行きました。

以下、vivado 2016.4 に付属の xilinx SDK で fsbl プロジェクトを新規に作成して試してみます。
以下、vivado 2016.4 に付属の xilinx SDK で fsbl プロジェクトを新規に作成して試しました。

結果として、vivado でも新規にプロジェクトを作成すると Petalinux と同様に
そのままでは動きませんでした。

そして、この問題は

- UART のチャンネル違い
- SD カード関連ライブラリのバグ

が原因であったことと、その回避方法が分かりました。>> [[[まとめ]に飛ぶ>#b01a5ab2]]

#contents

* fsbl2 プロジェクトの作成 [#uf03a5ca]

Xilinx SDK 2016.4 で Workspace に mys-xc7z020-trd.sdk を指定して開くと、
Project Explorer には

- design_1_wrapper_hw_platform_0
- fsbl
- fsbl_bsp

が表示されました。

&ref(projects.png,,66%);

[File]-[New]-[Project...] から [Xilinx]-[Application Project] を選び [Next]

&ref(new-project.png,,66%);

適当な名前を付けて [Next]

- OS Platform は standalone にします

&ref(new-project2.png,,66%);

Templates から [Zynq FSBL] を選択して [finish]

&ref(zynq-fsbl.png,,66%);

* コードの比較 [#w4ba4b71]

上記のようにして作った fsbl2 と、z-turn 付属の fsbl のコードを比較しました。

** Version & ChangeLog [#zb0103bc]

z-turn 付属のコードは "11.00a kv 10/08/14" ~
2016.4 で作成のコードは "16.00a gan 08/02/16" でした。

その間の ChangeLog は、

 * 12.00a ssc 12/11/14    839182 - FSBL -In the file sd.c, f_mount is called with
 *                       two arguments but f_mount is expecting the 3 arguments
 *                       from build 2015.1_1210_1, causing compilation error.
 *                        Resolution: Arguments for f_mount in InitSD() are
 *                        changed as per new signature.
 * 13.00a ssc 04/10/15    846899 - FSBL -In the file pcap.c, to clear DMA done
 *                       count, devcfg.INT_STS register is written to, which is
 *                       not correct.
 *                       Resolution: Corresponding fields in the devcfg.STATUS
 *                       register are written to, for clearing DMA done count.
 * 14.00a gan 01/13/16   869081 -(2016.1)FSBL -In qspi.c, FSBL picks the qspi
 *                        read command from LQSPI_CFG register instead of hard
 *                           coded read command (0x6B).
 * 15.00a gan 07/21/16   953654 -(2016.3)FSBL -In pcap.c/pcap.h/main.c,
 *                         Fabric Initialization sequence is modified to check
 *                         the PL power before sequence starts and checking INIT_B
 *                         reset status twice in case of failure.
 * 16.00a gan 08/02/16   Fix for CR# 955897 -(2016.3)FSBL -
 *                         In pcap.c, check pl power through MCTRL register
 *                         for 3.0 and later versions of silicon.

重要そうなところを抜き出すと、

- 13.00a : pcap.c で DMA done count をクリアする方法がおかしかったのを直した
- 15.00a : pcap.c/pcap.h/main.c にてエラーチェックを厳しくした
- 16.00a : pcap.c における PL Power チェック方法を 3.0 以上のシリコンバージョンに合わせて変更

となっています。

** 気づいたこと [#g44cec3a]

- 元々の fsbl プロジェクトは Debug モードでビルドされていた
- 全体を通じて、~
fsbl_printf(DEBUG_INFO, ... で %08x だったところが %08lx に変更されている

** 具体的な変更点 [#ie713420]

2つのプロジェクトの差分を取って比べてみます。

*** fsbl/src/main.c [#yf4185b6]

 + * 15.00a gan 07/21/16   Fix for CR# 953654 -(2016.3)FSBL -
 + * 			In pcap.c/pcap.h/main.c,
 + * 			Fabric Initialization sequence
 + * 			is modified to check the PL power
 + * 			before sequence starts and checking
 + * 			INIT_B reset status twice in case
 + * 			of failure.
   ...
   #ifdef STDOUT_BASEADDRESS
 + #ifdef XPAR_XUARTPS_0_BASEADDR
   #include "xuartps_hw.h"
 + #endif
   #endif
   ...
 
 -			FabricInit();
 + 			Status = FabricInit();
 +			if(Status != XST_SUCCESS){
 +				ClearFSBLIn();
 +				FsblHookFallback();
 +			}
   ...
 
   void OutputStatus(u32 State)
   {
   #ifdef STDOUT_BASEADDRESS
 + #ifdef XPAR_XUARTPS_0_BASEADDR
   	u32 UartReg = 0;
 + #endif
   
   	fsbl_printf(DEBUG_GENERAL,"FSBL Status = 0x%.4lx\r\n", State);
   	/*
   	 * The TX buffer needs to be flushed out
   	 * If this is not done some of the prints will not appear on the
   	 * serial output
   	 */
 + #ifdef XPAR_XUARTPS_0_BASEADDR
   	UartReg = Xil_In32(STDOUT_BASEADDRESS + XUARTPS_SR_OFFSET);
   	while ((UartReg & XUARTPS_SR_TXEMPTY) != XUARTPS_SR_TXEMPTY) {
   		UartReg = Xil_In32(STDOUT_BASEADDRESS + XUARTPS_SR_OFFSET);
   	}
 + #endif
   #endif
   }

どうやら #ifdef XPAR_XUARTPS_0_BASEADDR があちこちに追加されているのだけれど、
今の場合は fsbl_bsp\ps7_cortexa9_0\include\xparameters.h で、

 /* Canonical definitions for peripheral PS7_UART_0 */
 #define XPAR_XUARTPS_0_DEVICE_ID XPAR_PS7_UART_0_DEVICE_ID
 #define XPAR_XUARTPS_0_BASEADDR 0xE0000000
 #define XPAR_XUARTPS_0_HIGHADDR 0xE0000FFF
 #define XPAR_XUARTPS_0_UART_CLK_FREQ_HZ 100000000
 #define XPAR_XUARTPS_0_HAS_MODEM 0
 
 /* Canonical definitions for peripheral PS7_UART_1 */
 #define XPAR_XUARTPS_1_DEVICE_ID XPAR_PS7_UART_1_DEVICE_ID
 #define XPAR_XUARTPS_1_BASEADDR 0xE0001000
 #define XPAR_XUARTPS_1_HIGHADDR 0xE0001FFF
 #define XPAR_XUARTPS_1_UART_CLK_FREQ_HZ 100000000
 #define XPAR_XUARTPS_1_HAS_MODEM 0

と定義されていて、事前に main.c で読み込まれているため、問題にはならなさそう。

FabricInit() の戻り値がチェックされるようになったのだけれど、
これはすでに FsblFallback の中なので、ここに到達する時点でエラーが生じているはず。
これもあまり意味が無い。

main.c の流れを追うと、

- main() の中で、
-- ps7_init();          // PCW initialization for MIO,PLL,CLK and DDR
-- // この時点で fsbl_printf を利用可能
-- SlcrUnlock();        // Unlock SLCR for SLCR register write
-- Xil_DCacheFlush();   // Flush the Caches
-- Xil_DCacheDisable(); // Disable Data Cache
-- RegisterHandlers();  // Register the Exception handlers
-- fsbl_printf(DEBUG_GENERAL,"\n\rXilinx First Stage Boot Loader \n\r");

なので、ここまで順調に来ていれば初期メッセージが表示されるはず。

*** fsbl_bsp\ps7_cortexa9_0\include\xparameters.h [#va5b0042]

 - #define STDIN_BASEADDRESS 0xE0001000
 - #define STDOUT_BASEADDRESS 0xE0001000
 + #define STDIN_BASEADDRESS 0xE0000000
 + #define STDOUT_BASEADDRESS 0xE0000000

これ、ダメだ。

直前で見たとおり、~
0xE0001000 は XUARTPS_1 のアドレス、~
0xE0000000 は XUARTPS_0 のアドレス。
0xE0000000 は XUARTPS_0 のアドレス、~
なので、

これを 0xE0001000 に書き換えて試すと、、、~
やっぱりうんともすんとも言わないか。
これを 0xE0001000 に書き換える。

*** main.c の ps7_init() の直後でメッセージを表示 [#i34c57ef]

何も表示されない

*** fsbl/src/fsbl_debug.h [#l2aa1566]

 - #define	FSBL_DEBUG_INFO	1
   #define DEBUG_GENERAL	0x00000001    /* general debug  messages */
   #define DEBUG_INFO	0x00000002    /* More debug information */
   
   #if defined (FSBL_DEBUG_INFO)
   #define fsbl_dbg_current_types ((DEBUG_INFO) | (DEBUG_GENERAL))
   #elif defined (FSBL_DEBUG)
   #define fsbl_dbg_current_types (DEBUG_GENERAL)
   #else
   #define fsbl_dbg_current_types 0
   #endif
   
   #ifdef STDOUT_BASEADDRESS
   #define fsbl_printf(type,...) \
   		if (((type) & fsbl_dbg_current_types))  {xil_printf (__VA_ARGS__); }
   #else
   #define fsbl_printf(type, ...)
   #endif

さしあたってはこれが原因では無さそうだけれど、~
#define	FSBL_DEBUG_INFO	1 は復活させておく

*** ps7_init() [#a1a9eac6]
*** SD カードが読めないらしい [#oe06a9fa]

- init_data にある初期化手順を実行する形になっている
- ps7GetSiliconVersion() により初期化手順を選択する
上記の変更によりメッセージが表示されるようになった。

曰く、

 LANG:console
 Xilinx First Stage Boot Loader
 Release 2016.4  Mar 22 2017-23:06:54
 Devcfg driver initialized
 Silicon Version 3.1
 Boot mode is SD
 SD: rc= 0
 SD: Unable to open file BOOT.BIN: 3
                                    SD_INIT_FAIL
 FSBL Status = 0xA009
 
 This Boot Mode Doesn't Support Fallback
 In FsblHookFallback function

SD カードが読めないらしい。

古いコードでうまく行っているときは、

 LANG:console
 Xilinx First Stage Boot Loader
 Release 2014.4  Aug 11 2015-18:06:38
 Devcfg driver initialized
 Silicon Version 3.1
 Boot mode is SD
 SD: rc= 0
 SD Init Done
 Flash Base Address: 0xE0100000
 Reboot status register: 0x60600000
 Multiboot Register: 0x0000C000
 Image Start Address: 0x00000000
 Partition Header Offset:0x00000C80
 Partition Count: 2
 Partition Number: 1

となる。

コード上では "Boot mode is SD" の後は InitSD が呼ばれる。

*** fsbl/src/sd.c [#w85c4e43]

 LANG:c
 unsigned long *ps7_mio_init_data = ps7_mio_init_data_3_0;
 unsigned long *ps7_pll_init_data = ps7_pll_init_data_3_0;
 unsigned long *ps7_clock_init_data = ps7_clock_init_data_3_0;
 unsigned long *ps7_ddr_init_data = ps7_ddr_init_data_3_0;
 unsigned long *ps7_peripherals_init_data = ps7_peripherals_init_data_3_0;
 
 int
 ps7_init() 
 {
   unsigned long si_ver = ps7GetSiliconVersion ();
   int ret;
 
   if (si_ver == PCW_SILICON_VERSION_1) {
     ps7_mio_init_data = ps7_mio_init_data_1_0;
     ps7_pll_init_data = ps7_pll_init_data_1_0;
     ps7_clock_init_data = ps7_clock_init_data_1_0;
     ps7_ddr_init_data = ps7_ddr_init_data_1_0;
     ps7_peripherals_init_data = ps7_peripherals_init_data_1_0;
   } else if (si_ver == PCW_SILICON_VERSION_2) {
     ps7_mio_init_data = ps7_mio_init_data_2_0;
     ps7_pll_init_data = ps7_pll_init_data_2_0;
     ps7_clock_init_data = ps7_clock_init_data_2_0;
     ps7_ddr_init_data = ps7_ddr_init_data_2_0;
     ps7_peripherals_init_data = ps7_peripherals_init_data_2_0;
   } else {
     ps7_mio_init_data = ps7_mio_init_data_3_0;
     ps7_pll_init_data = ps7_pll_init_data_3_0;
     ps7_clock_init_data = ps7_clock_init_data_3_0;
     ps7_ddr_init_data = ps7_ddr_init_data_3_0;
     ps7_peripherals_init_data = ps7_peripherals_init_data_3_0;
   u32 InitSD(const char *filename)
   {
   
       FRESULT rc;
 +     TCHAR *path = "0:/"; /* Logical drive number is 0 */
   
       /* Register volume work area, initialize device */
 -     rc = f_mount(0, &fatfs);
 +     rc = f_mount(&fatfs, path, 0);
       fsbl_printf(DEBUG_INFO,"SD: rc= %.8x\n\r", rc);
   
       if (rc != FR_OK) {
           return XST_FAILURE;
       }
   
       strcpy_rom(buffer, filename);
       boot_file = (char *)buffer;
       FlashReadBaseAddress = XPAR_PS7_SD_0_S_AXI_BASEADDR;
   
       rc = f_open(&fil, boot_file, FA_READ);
       if (rc) {
           fsbl_printf(DEBUG_GENERAL,"SD: Unable to open file %s: %d\n", boot_file, rc);
           return XST_FAILURE;
       }
   
       return XST_SUCCESS;
   
   }
 
   ret = ps7_config (ps7_mio_init_data);  
   if (ret != PS7_INIT_SUCCESS) return ret;
 
   ret = ps7_config (ps7_pll_init_data); 
   if (ret != PS7_INIT_SUCCESS) return ret;
 
   ret = ps7_config (ps7_clock_init_data);
   if (ret != PS7_INIT_SUCCESS) return ret;
 
   ret = ps7_config (ps7_ddr_init_data);
   if (ret != PS7_INIT_SUCCESS) return ret;
 
   ret = ps7_config (ps7_peripherals_init_data);
   if (ret != PS7_INIT_SUCCESS) return ret;
   return PS7_INIT_SUCCESS;
 }

シリコンバージョンはメモリの値を読むだけなので失敗しようがないし、
そもそもこのあたりのコードはうまく行く方も行かない方も共通。
f_mount は fsbl_bsp\ps7_cortexa9_0\include\ff.h で定義されていて、

 LANG:c
 unsigned long
 ps7GetSiliconVersion () {
   // Read PS version from MCTRL register [31:28]
   unsigned long mask = 0xF0000000;
   unsigned long *addr = (unsigned long*) 0XF8007080;    
   unsigned long ps_version = (*addr & mask) >> 28;
   return ps_version;
 }
 - FRESULT f_mount (BYTE, FATFS*);	
 + FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt);

 LANG:c
 int
 ps7_config(unsigned long * ps7_config_init) 
のように変更されている。

*** fsbl_bsp\ps7_cortexa9_0\libsrc\xilffs_v?_?\src\ff.c [#l1ec7a8e]

f_mount は ff.c にある。

Changelog によれば差分は、

 / Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write().
 /                   f_lseek() reports required table size on creating CLMP.
 /                   Extended format syntax of f_printf().
 /                   Ignores duplicated directory separators in given path name.
 /
 / Sep 06,'11 R0.09  f_mkfs() supports multiple partition to complete the multiple partition feature.
 /                   Added f_fdisk().
 / Aug 27,'12 R0.09a Changed f_open() and f_opendir() reject null object pointer to avoid crash.
 /                   Changed option name _FS_SHARE to _FS_LOCK.
 /                   Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
 / Jan 24,'13 R0.09b Added f_setlabel() and f_getlabel().
 /
 / Oct 02,'13 R0.10  Added selection of character encoding on the file. (_STRF_ENCODE)
 /                   Added f_closedir().
 /                   Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO)
 /                   Added forced mount feature with changes of f_mount().
 /                   Improved behavior of volume auto detection.
 /                   Improved write throughput of f_puts() and f_printf().
 /                   Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
 /                   Fixed f_write() can be truncated when the file size is close to 4GB.
 /                   Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect error code.
 / Jan 15,'14 R0.10a Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID)
 /                   Added a configuration option of minimum sector size. (_MIN_SS)
 /                   2nd argument of f_rename() can have a drive number and it will be ignored.
 /                   Fixed f_mount() with forced mount fails when drive number is >= 1.
 /                   Fixed f_close() invalidates the file object without volume lock.
 /                   Fixed f_closedir() returns but the volume lock is left acquired.
 /                   Fixed creation of an entry with LFN fails on too many SFN collisions.
 / May 19,'14 R0.10b Fixed a hard error in the disk I/O layer can collapse the directory entry.
 /                   Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN.

とのこと。

 FRESULT f_mount (
     BYTE vol,       /* Logical drive number to be mounted/unmounted */
     FATFS *fs       /* Pointer to new file system object (NULL for unmount)*/
 )
 {
     unsigned long *ptr = ps7_config_init;
     FATFS *rfs;
 
     unsigned long  opcode;            // current instruction ..
     unsigned long  args[16];           // no opcode has so many args ...
     int  numargs;           // number of arguments of this instruction
     int  j;                 // general purpose index
     if (vol >= _VOLUMES)            /* Check if the drive number is valid */
         return FR_INVALID_DRIVE;
     rfs = FatFs[vol];               /* Get current fs object */

だったところが、

 FRESULT f_mount (
     FATFS* fs,          /* Pointer to the file system object (NULL:unmount)*/
     const TCHAR* path,  /* Logical drive number to be mounted/unmounted */
     BYTE opt            /* 0:Do not mount (delayed mount), 1:Mount immediately */
 )
 {
     FATFS *cfs;
     s32 vol;
     FRESULT res;
     const TCHAR *rp = path;
 
     volatile unsigned long *addr;         // some variable to make code readable
     unsigned long  val,mask;              // some variable to make code readable
     vol = get_ldnumber(&rp);
     if (vol < 0) {return FR_INVALID_DRIVE;}
     cfs = FatFs[vol];                   /* Pointer to fs object */

になっている。

InitSD からの呼び出しが opt = 0 すなわち Do not mount (delayed mount) 
になっているのは問題ないんだろうか?

これを 1 にしたところ、
 LANG:console
 Xilinx First Stage Boot Loader
 Release 2016.4  Mar 22 2017-23:54:30
 Devcfg driver initialized
 Silicon Version 3.1
 Boot mode is SD
 SD: rc= 3
 SD_INIT_FAIL
 FSBL Status = 0xA009
 
     int finish = -1 ;           // loop while this is negative !
     int i = 0;                  // Timeout variable
     
     while( finish < 0 ) {
         numargs = ptr[0] & 0xF;
         opcode = ptr[0] >> 4;
 This Boot Mode Doesn't Support Fallback
 In FsblHookFallback function

となって、どうやら悪化したため、元に戻した。


*** f_open のエラー番号 [#k236af09]

 SD: Unable to open file BOOT.BIN: 3

の 3 が f_open のエラー番号で、ここでは FR_NOT_READY にあたる。

コードとしては、
 	/* Get disk statics */
 	stat = disk_initialize(pdrv);
 	if (stat & STA_NOINIT) {
 		return FR_NOT_READY;
 	}

なので、disk_initialize が失敗している。

*** fsbl_bsp\ps7_cortexa9_0\libsrc\xilffs_v?_?\src\diskio.c [#d7aee870]

disk_initialize では、どんなエラーでも STA_NOINIT が立つので、
これだけでは何がいけないのかよく分からない。

xil_printf を入れまくってエラー箇所を探したところ、

 XSdPs_CfgInitialize(&SdInstance[pdrv], SdConfig, SdConfig->BaseAddress);

がエラーコード 1 を吐いている。とはいえこれは XST_FAILURE なので、原因は・・・不明?

*** fsbl2_bsp\ps7_cortexa9_0\libsrc\sdps_v3_1\src\xsdps.c [#rd174c31]

どうやら XSdPs_Change_ClkFreq が エラーコード 1 を吐いている。

この関数は古いコードではここに無かった。

*** fsbl2_bsp\ps7_cortexa9_0\libsrc\sdps_v3_1\src\xsdps_options.c [#xbae5227]

XSdPs_Change_ClkFreq のエラーは No valid divisor found for given frequency
なので、計算できないというのはかなりおかしい。

 LANG:c
         /* Calculate divisor */
         DivCnt = 0x1U;
         while (DivCnt <= XSDPS_CC_MAX_DIV_CNT) {
             if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
                 Divisor = DivCnt / 2U;
                 break;
             }
             DivCnt = DivCnt << 1U;
         }
 
         for( j = 0 ; j < numargs ; j ++ ) 
             args[j] = ptr[j+1];
         ptr += numargs + 1;
         
         
         switch ( opcode ) {
             
         case OPCODE_EXIT:
             finish = PS7_INIT_SUCCESS;
         if (DivCnt > XSDPS_CC_MAX_DIV_CNT) {
             /* No valid divisor found for given frequency */
             Status = XST_FAILURE;
             goto RETURN_PATH;
         }

の部分で、
- InstancePtr->Config.InputClockHz = 125000000
- XSDPS_CC_MAX_DIV_CNT = 256
- SelFreq = 400000

となってエラーが出ていた。

古いコードでは

 LANG:c
     DivCnt = 0x1;
     for(ClkLoopCnt = 0; ClkLoopCnt < XSDPS_CC_MAX_NUM_OF_DIV;
         ClkLoopCnt++) {
         if( ((InstancePtr->Config.InputClockHz)/DivCnt) <= SelFreq) {
             Divisor = DivCnt/2;
             Divisor = Divisor << XSDPS_CC_DIV_SHIFT;
             break;
             
         case OPCODE_CLEAR:
             addr = (unsigned long*) args[0];
             *addr = 0;
             break;
 
         case OPCODE_WRITE:
             addr = (unsigned long*) args[0];
             val = args[1];
             *addr = val;
             break;
 
         case OPCODE_MASKWRITE:
             addr = (unsigned long*) args[0];
             mask = args[1];
             val = args[2];
             *addr = ( val & mask ) | ( *addr & ~mask);
             break;
 
         case OPCODE_MASKPOLL:
             addr = (unsigned long*) args[0];
             mask = args[1];
             i = 0;
             while (!(*addr & mask)) {
                 if (i == PS7_MASK_POLL_TIME) {
                     finish = PS7_INIT_TIMEOUT;
                     break;
                 }
                 i++;
             }
             break;
         case OPCODE_MASKDELAY:
             addr = (unsigned long*) args[0];
             mask = args[1];
             int delay = get_number_of_cycles_for_delay(mask);
             perf_reset_and_start_timer(); 
             while ((*addr < delay)) {
             }
             break;
         default:
             finish = PS7_INIT_CORRUPT;
             break;
         }
         DivCnt = DivCnt << 1;
     }
     return finish;
 }
 
     if(ClkLoopCnt == 9) {
         /*
          * No valid divisor found for given frequency
          */
         Status = XST_FAILURE;
         goto RETURN_PATH;
     }

#define PS7_MASK_POLL_TIME 100000000
で、ほとんど同じコードと言える。

*** fsbl_bsp\ps7_cortexa9_0\libsrc\standalone_v?_?\src\xil_printf.c [#l276479b]
こちらは、
- InstancePtr->Config.InputClockHz = 125000000
- XSDPS_CC_MAX_NUM_OF_DIV = 8
- SelFreq = 25000000

最終的には outbyte を呼び出す
なので、4 回のループで抜けている。

*** fsbl_bsp\ps7_cortexa9_0\libsrc\standalone_v?_?\src\outbyte.c [#m4edd7e6]
エラーとなっているのは新しいコードの XSdPs_CfgInitialize 内の

バージョン間で変更なし
 	Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_400_KHZ);

 LANG:c
 void outbyte(char c) {
 	 XUartPs_SendByte(STDOUT_BASEADDRESS, c);
 }
なのだけれど、実は XSdPs_CardInitialize には

*** fsbl_bsp\ps7_cortexa9_0\libsrc\uartps_v?_?\src\xuartps.c [#kcf29b72]
		if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3)
			InstancePtr->BusSpeed = SD_CLK_19_MHZ;
		else
			InstancePtr->BusSpeed = SD_CLK_25_MHZ;
		Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);

かなりいろいろ変更されていて厳しい、が、どうやらキャストを増やしてたりする感じ。
というコードがあって、こっちは古いコードと同様にうまく行くはず。

ここまで来て、ようやく以下の記事を見つけました。

https://forums.xilinx.com/t5/Embedded-Development-Tools/Zynq-FSBL-won-t-read-boot-bin-from-SD-card-with-CD-disabled/td-p/572037

曰く、

 	Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_400_KHZ);


 	Status = XSdPs_Change_ClkFreq(InstancePtr, SD_CLK_25_MHZ);

に直しちゃえば?

とのこと。

** その結果、起動した [#mbd375e8]

後から分かったことには、ライブラリソースをいじる代わりに、

http://nahitafu.cocolog-nifty.com/nahitafu/2014/08/zynqfsbl-5f71.html

のように、PS ブロックの設定で SDIO のクロックを例えば 50MHz 
まで下げることでこのバグ(?)に対応することも可能なようでした。

* まとめ [#b01a5ab2]

** UART のチャンネルを変更 [#f4325941]

UART のチャンネルが 0 でなく 1 なのに対応して、~
fsbl_bsp\ps7_cortexa9_0\include\xparameters.h にて、

 #define STDIN_BASEADDRESS 0xE0001000
 #define STDOUT_BASEADDRESS 0xE0001000

とする。

** SD カード関連ライブラリのバグ(?)を除去 [#k5175fe8]

fsbl2_bsp\ps7_cortexa9_0\libsrc\sdps_v3_1\src\xsdps.c にて

	Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_400_KHZ);



	Status = XSdPs_Change_ClkFreq(InstancePtr, SD_CLK_25_MHZ);

に変更。

あるいは、

http://nahitafu.cocolog-nifty.com/nahitafu/2014/08/zynqfsbl-5f71.html

のように、PS ブロックの設定で SDIO のクロックを例えば 50MHz まで下げる。
** (オプション)すべての debug メッセージを表示する [#h06838f8]

fsbl/src/fsbl_debug.h

 #define DEBUG_GENERAL	0x00000001

の前に

 #define	FSBL_DEBUG_INFO	1

を追加

* 質問・コメント [#z7ff73d4]

#article_kcaptcha


Counter: 13429 (from 2010/06/03), today: 1, yesterday: 0