安德鲁

[笔记].怎样使用Nios II中的Memory Test模板来测试RAM和Flash.[Memory][Nios II][SOPC Builder]

0
阅读(4191)

本文简单描述如何使用Memory Test模板来测试RAM和Flash,此处以SDRAM和EPCS为例。

使用环境:Altera Quartus 9.1 SP1 + Nios II  9.1 Software Build Tools for Eclipse SP1

步骤1 在SOPC Builder中配置RAM和FLash

图1 例化epcs控制器和sdram控制器

注意观察epcs控制器和sdram控制器的起始和终止地址。此处epcs controller,例化为epcs,起始地址是0x01002090,终止地址是0x01002097;sdram controller,与epcs类似。当然也可查看之后生成的system.h。

步骤2 使用Nios II中的Memory Test模板来测试

1. 使用Memory Test模板创建软件工程

图2 创建软件工程

2. 编译程序及检查相关设置

编程成功后,打开system.h,查看与存储器相关的映射内容。

1 #define ALT_MODULE_CLASS_epcs altera_avalon_epcs_flash_controller
2 #define EPCS_BASE 0x1001800
3 #define EPCS_IRQ 1
4 #define EPCS_IRQ_INTERRUPT_CONTROLLER_ID 0
5 #define EPCS_NAME "/dev/epcs"
6 #define EPCS_REGISTER_OFFSET 512
7 #define EPCS_SPAN 2048
8 #define EPCS_TYPE "altera_avalon_epcs_flash_controller"

代码1 EPCS相关的映射

01 #define ALT_MODULE_CLASS_sdram altera_avalon_new_sdram_controller
02 #define SDRAM_BASE 0x800000
03 #define SDRAM_CAS_LATENCY 3
04 #define SDRAM_CONTENTS_INFO ""
05 #define SDRAM_INIT_NOP_DELAY 0.0
06 #define SDRAM_INIT_REFRESH_COMMANDS 2
07 #define SDRAM_IRQ -1
08 #define SDRAM_IRQ_INTERRUPT_CONTROLLER_ID -1
09 #define SDRAM_IS_INITIALIZED 1
10 #define SDRAM_NAME "/dev/sdram"
11 #define SDRAM_POWERUP_DELAY 100.0
12 #define SDRAM_REFRESH_PERIOD 15.625
13 #define SDRAM_REGISTER_DATA_IN 1
14 #define SDRAM_SDRAM_ADDR_WIDTH 22
15 #define SDRAM_SDRAM_BANK_WIDTH 2
16 #define SDRAM_SDRAM_COL_WIDTH 8
17 #define SDRAM_SDRAM_DATA_WIDTH 16
18 #define SDRAM_SDRAM_NUM_BANKS 4
19 #define SDRAM_SDRAM_NUM_CHIPSELECTS 1
20 #define SDRAM_SDRAM_ROW_WIDTH 12
21 #define SDRAM_SHARED_DATA 0
22 #define SDRAM_SIM_MODEL_BASE 1
23 #define SDRAM_SPAN 8388608
24 #define SDRAM_STARVATION_INDICATOR 0
25 #define SDRAM_TRISTATE_BRIDGE_SLAVE ""
26 #define SDRAM_TYPE "altera_avalon_new_sdram_controller"
27 #define SDRAM_T_AC 5.5
28 #define SDRAM_T_MRD 3
29 #define SDRAM_T_RCD 20.0
30 #define SDRAM_T_RFC 70.0
31 #define SDRAM_T_RP 20.0
32 #define SDRAM_T_WR 14.0

代码2 SDRAM相关的映射

3. 运行程序

运行程序后,在Nios II Console出现如下字样。

图3 Nios II Console 显示结果

此命令行界面,提示输入a,测试RAM;输入b,测试Flash;输入q,退出。

由于程序是在SDRAM中运行的,那么我们先测试EPCS。选择b,回车;接下来输入EPCS设备名,出现如下提示。

图4 提示测试EPCS Flash

命令行提示,EPCS设备已经打开;区域0有8个块等信息;并询问是否测试块3。此处选择y,开始测试。

图5 测试EPCS

在EPCS的块3,写Flash和读Flash操作被测试完毕。然后自动关闭EPCS设备。

回车后,选择a,接着测试SDRAM。

图6 提示输入测试SDRAM的起始地址

提示输入其实地址。从system.h可以看到,SDRAM从0x800000开始寻址;在SOPC Builder中,更可以清楚地了解到SDRAM的起始和终止地址。然而,程序是在SDRAM中运行的;如果在此处,直接输入SDRAM寻址的起始地址,有可能引起冲突,以致于程序无法继续运行下去。那我们先测试其他地址开始的内容,此处以0x900000为例。

图6 提示输入测试SDRAM的终止地址

输入大于测试SDRAM的起始地址的地址即可,此处以0xA00000为例。

图7 输入测试SDRAM的终止地址,显示测试结果

测试结果显示:从地址0x900000到地址0xA00000,数据总线测试通过;地址总线测试通过,字节和半字数据接入测试通过;单独位测试通过。

 

附录1 mem_test.c

此处,水平有限,不做解析,请读者自行分析。着重分析和学习其中的存储器操作方法。

0001 /**************************************************************************
0002  * Copyright (c) 2004 Altera Corporation, San Jose, California, USA.      *
0003  * All rights reserved. All use of this software and documentation is     *
0004  * subject to the License Agreement located at the end of this file below.*
0005  *************************************************************************/
0006 /**************************************************************************
0007  *
0008  
0009  * Description
0010  *************** 
0011  * This is a test program which tests RAM and flash memory. 
0012  *
0013  
0014  * Requirements
0015  ****************
0016  * This is a "Hosted" application. According to the ANSI C standard, hosted 
0017  * applications can rely on numerous system-services (including properly-
0018  * initialized device drivers and, in this case, STDOUT).  
0019  
0020  * When this program is compiled, code is added before main(), so that all 
0021  * devices are properly-initialized and all system-services (e.g. the <STDIO>
0022  * library) are ready-to-use. In this hosted environment, all standard C 
0023  * programs will run.
0024  
0025  * A hosted application (like this example) does not need to concern itself 
0026  * with initializing devices. As long as it only calls C Standard Library 
0027  * functions, a hosted application can run "as if on a workstation."
0028  
0029  * An application runs in a hosted environment if it declares the function 
0030  * main(), which this application does.
0031  
0032  * This software example requires a STDOUT component such as a UART or 
0033  * JTAG UART, a CFI flash component, and 2 RAM components (one for running
0034  * the program, and one for testing)  Therefore it can run on the following
0035  * hardware examples:
0036  
0037  * Nios Development Board, Stratix II Edition:
0038  * -  Standard (DMA RAM test will not run)
0039  * -  Full Featured
0040  *
0041  * DSP Development Board, Stratix II Edition:
0042  * -  Standard (DMA RAM test will not run)
0043  * -  Full Featured
0044  *
0045  * Nios Development Board, Stratix Edition:
0046  * -  Standard (DMA RAM test will not run)
0047  * -  Full Featured
0048  
0049  * Nios Development Board, Stratix Professional Edition:
0050  * -  Standard (DMA RAM test will not run)
0051  * -  Full Featured
0052  
0053  * Nios Development Board, Cyclone Edition:
0054  * -  Standard (DMA RAM test will not run)
0055  * -  Full Featured
0056  *
0057  * Nios Development Board, Cyclone II Edition:
0058  * -  Standard (DMA RAM test will not run)
0059  * -  Full Featured
0060  *
0061  * Note: This example will not run on the Nios II Instruction Set Simulator
0062  
0063  * Peripherals Exercised by SW
0064  *******************************
0065  * The example's purpose is to test RAM and flash, as well as demonstrate the 
0066  * use of the DMA controller and flash API in NiosII.
0067  
0068  * The RAM test routine performs the following operations:
0069  * 1.) Tests the address and data lines for shorts and opens. 
0070  * 2.) Tests byte and half-word access.
0071  * 3.) Tests every bit in the memory to store both '1' and '0'. 
0072  * 4.) Tests DMA access to the memory.
0073  *
0074  * IMPORTANT: The RAM test is destructive to the contents of the RAM.  For this
0075  * reason, you MUST assure that none of the software sections are located in 
0076  * the RAM being tested.  This requires that code, data, and exception 
0077  * locations must all be in a memory seperate from the one being tested.
0078  * These locations can be adjusted in Nios II IDE and SOPC Builder.
0079  *
0080  *  
0081  * The flash tests demonstrate the use of the flash programming API.  After the
0082  * flash device specified is opened, the test routine searches for a block in 
0083  * the device that is already erased.  This prevents any overwriting of 
0084  * important data that may be programmed in flash.  When an erased block is 
0085  * found, the routine performs a test of the flash API calls on that block.
0086  *
0087  * The following API functions are then run to test the flash interface:
0088  
0089  * - alt_get_flash_info
0090  *    This function queries the flash device and collects various information 
0091  *    about it.  In the example, the results of this query are compared to what
0092  *    is expected, and an error is reported in the event of a mismatch.
0093  * - alt_write_flash
0094  *    This function writes a specified number of bytes to the flash device.  
0095  *    In the example, this function is called repeatedly in a loop to write a 
0096  *    lengthy amount of data.
0097  * - alt_read_flash
0098  *    This function reads a specified number of bytes of data from the flash 
0099  *    device.  In the example, alt_read_flash is used to read back and test 
0100  *    all of the writing routines.
0101  * - alt_erase_flash_block
0102  *    This function performs a block erase on the flash device. 
0103  * - alt_write_flash_block
0104  *    This function writes an erase block of data to the flash device.  
0105  
0106  * During the test, status and error information is passed to the user via 
0107  * printf's.
0108  
0109  * Software Files
0110  ******************
0111  * memtest.c - Main C file that contains all memory testing code in this 
0112  *             example.
0113  
0114  **************************************************************************/
0115  
0116  
0117 #include <STDIO.H>
0118 #include <ALT_TYPES.H>
0119 #include <IO.H>
0120 #include <SYSTEM.H>
0121 #include <STRING.H>
0122  
0123 #include "sys/alt_dma.h"
0124 #include "system.h"
0125 #include "sys/alt_flash.h"
0126 #include "sys/alt_flash_dev.h"
0127  
0128 /* Mode parameters for Flash Test */
0129 #define TEST 1
0130 #define SHOWMAP 2
0131 #define CFI 3
0132 #define EPCS 4
0133 #define QUIT_WITHOUT_TESTING -1
0134  
0135 /* One nice define for going to menu entry functions. */
0136 #define MenuCase(letter,proc) case letter:proc; break;
0137  
0138 /* Global DMA "transaction finished" flag */
0139 #ifdef DMA_NAME  
0140 static volatile int rx_done = 0;
0141 #endif /* DMA_NAME */  
0142  
0143 /******************************************************************
0144 *  Function: MenuHeader
0145 *
0146 *  Purpose: Prints the menu header.
0147 *
0148 ******************************************************************/
0149 static void MenuHeader(void)
0150 {
0151   printf("\n\n");
0152   printf("             <---->   Nios II Memory Test.   <---->\n");
0153   printf("This software example tests the memory in your system to assure it\n");
0154   printf("is working properly.  This test is destructive to the contents of\n");
0155   printf("the memory it tests. Assure the memory being tested does not contain\n");
0156   printf("the executable or data sections of this code or the exception address\n");
0157   printf("of the system.\n");
0158 }
0159  
0160 /******************************************************************
0161 *  Function: MenuBegin
0162 *
0163 *  Purpose: Prints the top portion of the menu.
0164 *
0165 ******************************************************************/
0166 static void MenuBegin( char *title )
0167 {
0168   printf("\n\n");
0169   printf("----------------------------------\n");
0170   printf("%s\n",title);
0171   printf("----------------------------------\n");
0172 }
0173  
0174 /******************************************************************
0175 *  Function: MenuItem
0176 *
0177 *  Purpose: Prints selection items in the menu, enumerated by the 
0178 *           specified letter.
0179 *
0180 ******************************************************************/
0181 static void MenuItem( char letter, char *name )
0182 {
0183   printf("     %c:  %s\n" ,letter, name);
0184 }
0185  
0186 /******************************************************************
0187 *  Function: GetInputString
0188 *
0189 *  Purpose: Parses an input string for the character '\n'.  Then
0190 *           returns the string, minus any '\r' characters it 
0191 *           encounters.
0192 *
0193 ******************************************************************/
0194 void GetInputString( char* entry, int size, FILE * stream )
0195 {
0196   int i;
0197   int ch = 0;
0198    
0199   for(i = 0; (ch != '\n') && (i < size); )
0200   {
0201     if( (ch = getc(stream)) != '\r')
0202     {
0203       entry[i] = ch;
0204       i++;
0205     }
0206   }
0207 }
0208  
0209 /******************************************************************
0210 *  Function: MenuEnd
0211 *
0212 *  Purpose: Prints the end of the menu, then captures and returns
0213 *           the user's selection.
0214 *
0215 ******************************************************************/
0216 static int MenuEnd( char lowLetter, char highLetter )
0217 {
0218   static char entry[4];
0219   static char ch;
0220  
0221   printf("     q:  Exit\n");
0222   printf("----------------------------------\n");
0223   printf("\nSelect Choice (%c-%c): [Followed by <ENTER>]",lowLetter,highLetter);
0224  
0225   GetInputString( entry, sizeof(entry), stdin );
0226   if(sscanf(entry, "%c\n", &ch))
0227   {
0228     if( ch >= 'A' && ch <= 'Z' )
0229       ch += 'a' - 'A';
0230     if( ch == 27 )
0231       ch = 'q';
0232   }
0233   return ch;
0234 }
0235  
0236 /******************************************************************
0237 *  Function: MemGetAddressRange
0238 *
0239 *  Purpose: Gathers a range of memory from the user.
0240 *
0241 ******************************************************************/
0242 static int MemGetAddressRange(int* base_address, int* end_address)
0243 {
0244  
0245   char line[12];
0246  
0247   while(1)
0248   {
0249     /* Get the base address */
0250     printf("Base address to start memory test: (i.e. 0x800000)\n");
0251     printf(">");
0252  
0253     GetInputString( line, sizeof(line), stdin );
0254     
0255     /* Check the format to make sure it was entered as hex */
0256     if(sscanf(line, "0x%X", base_address) != 1)
0257     {
0258       printf("%s\n", line);
0259       printf(" -ERROR: Invalid base address entered.  Address must be in the form '0x800000'\n\n");
0260       continue;
0261     }
0262      
0263     /* Get the end address */
0264     printf("End Address:\n");
0265     printf(">");
0266  
0267     GetInputString( line, sizeof(line), stdin );
0268      
0269     /* Check the format to make sure it was entered as hex */
0270     if(sscanf(line, "0x%X", end_address) != 1)
0271     {
0272       printf(" -ERROR: Invalid end address entered.  Address must be in the form '0x8FFFFF'\n\n");
0273       continue;
0274     }
0275      
0276     /* Make sure end address is greater than base address. */
0277     if (end_address <= base_address)
0278     {
0279       printf(" -ERROR: End address must be greater than the start address\n\n");
0280  
0281       continue;
0282     }
0283     break;
0284   }
0285  
0286   return(0);
0287 }
0288  
0289 /******************************************************************
0290 *  Function: MemTestDataBus
0291 *
0292 *  Purpose: Tests that the data bus is connected with no 
0293 *           stuck-at's, shorts, or open circuits.
0294 *
0295 ******************************************************************/
0296 static int MemTestDataBus(unsigned int address)
0297 {
0298   unsigned int pattern;
0299   unsigned int ret_code = 0x0;
0300  
0301   /* Perform a walking 1's test at the given address. */
0302   for (pattern = 1; pattern != 0; pattern <<= 1)
0303   {
0304     /* Write the test pattern. */
0305     IOWR_32DIRECT(address, 0, pattern);
0306  
0307     /* Read it back (immediately is okay for this test). */
0308     if (IORD_32DIRECT(address, 0) != pattern)
0309     {
0310       ret_code = pattern;
0311       break;
0312     }
0313   }
0314   return ret_code;
0315 }
0316  
0317  
0318 /******************************************************************
0319 *  Function: MemTestAddressBus
0320 *
0321 *  Purpose: Tests that the address bus is connected with no 
0322 *           stuck-at's, shorts, or open circuits.
0323 *
0324 ******************************************************************/
0325 static int MemTestAddressBus(unsigned int memory_base, unsigned int nBytes)
0326 {
0327   unsigned int address_mask = (nBytes - 1);
0328   unsigned int offset;
0329   unsigned int test_offset;
0330  
0331   unsigned int pattern     = 0xAAAAAAAA;
0332   unsigned int antipattern  = 0x55555555;
0333  
0334   unsigned int ret_code = 0x0;
0335  
0336   /* Write the default pattern at each of the power-of-two offsets. */
0337   for (offset = sizeof(unsigned int); (offset & address_mask) != 0; offset <<= 1)
0338   {
0339     IOWR_32DIRECT(memory_base, offset, pattern);
0340   }
0341  
0342   /* Check for address bits stuck high. */
0343   test_offset = 0;
0344   IOWR_32DIRECT(memory_base, test_offset, antipattern);
0345   for (offset = sizeof(unsigned int); (offset & address_mask) != 0; offset <<= 1)
0346   {
0347      if (IORD_32DIRECT(memory_base, offset) != pattern)
0348      {
0349         ret_code = (memory_base+offset);
0350         break;
0351      }
0352   }
0353  
0354   /* Check for address bits stuck low or shorted. */
0355   IOWR_32DIRECT(memory_base, test_offset, pattern);
0356   for (test_offset = sizeof(unsigned int); (test_offset & address_mask) != 0; test_offset <<= 1)
0357   {
0358     if (!ret_code)
0359     {
0360       IOWR_32DIRECT(memory_base, test_offset, antipattern);
0361       for (offset = sizeof(unsigned int); (offset & address_mask) != 0; offset <<= 1)
0362       {
0363         if ((IORD_32DIRECT(memory_base, offset) != pattern) && (offset != test_offset))
0364         {
0365           ret_code = (memory_base + test_offset);
0366           break;
0367         }
0368       }
0369       IOWR_32DIRECT(memory_base, test_offset, pattern);
0370     }
0371   }
0372  
0373   return ret_code;
0374 }
0375  
0376  
0377 /******************************************************************
0378 *  Function: MemTest8_16BitAccess
0379 *
0380 *  Purpose: Tests that the memory at the specified base address
0381 *           can be read and written in both byte and half-word 
0382 *           modes.
0383 *
0384 ******************************************************************/
0385 static int MemTest8_16BitAccess(unsigned int memory_base)
0386 {
0387   int ret_code = 0x0;
0388  
0389   /* Write 4 bytes */
0390   IOWR_8DIRECT(memory_base, 0, 0x0A);
0391   IOWR_8DIRECT(memory_base, 1, 0x05);
0392   IOWR_8DIRECT(memory_base, 2, 0xA0);
0393   IOWR_8DIRECT(memory_base, 3, 0x50);
0394  
0395   /* Read it back as one word */
0396   if(IORD_32DIRECT(memory_base, 0) != 0x50A0050A)
0397   {
0398     ret_code = memory_base;
0399   }
0400  
0401   /* Read it back as two half-words */
0402   if (!ret_code)
0403   {
0404     if ((IORD_16DIRECT(memory_base, 2) != 0x50A0) ||
0405         (IORD_16DIRECT(memory_base, 0) != 0x050A))
0406     {
0407       ret_code = memory_base;
0408     }
0409   }
0410  
0411   /* Read it back as 4 bytes */
0412   if (!ret_code)
0413   {
0414     if ((IORD_8DIRECT(memory_base, 3) != 0x50) ||
0415         (IORD_8DIRECT(memory_base, 2) != 0xA0) ||
0416         (IORD_8DIRECT(memory_base, 1) != 0x05) ||
0417         (IORD_8DIRECT(memory_base, 0) != 0x0A))
0418     {
0419     ret_code = memory_base;
0420     }
0421   }
0422  
0423   /* Write 2 half-words */
0424   if (!ret_code)
0425   {
0426     IOWR_16DIRECT(memory_base, 0, 0x50A0);
0427     IOWR_16DIRECT(memory_base, 2, 0x050A);
0428  
0429     /* Read it back as one word */
0430     if(IORD_32DIRECT(memory_base, 0) != 0x050A50A0)
0431     {
0432       ret_code = memory_base;
0433     }
0434   }
0435  
0436   /* Read it back as two half-words */
0437   if (!ret_code)
0438   {
0439     if ((IORD_16DIRECT(memory_base, 2) != 0x050A) ||
0440         (IORD_16DIRECT(memory_base, 0) != 0x50A0))
0441     {
0442       ret_code = memory_base;
0443     }
0444   }
0445  
0446   /* Read it back as 4 bytes */
0447   if (!ret_code)
0448   {
0449     if ((IORD_8DIRECT(memory_base, 3) != 0x05) ||
0450         (IORD_8DIRECT(memory_base, 2) != 0x0A) ||
0451         (IORD_8DIRECT(memory_base, 1) != 0x50) ||
0452         (IORD_8DIRECT(memory_base, 0) != 0xA0))
0453     {
0454       ret_code = memory_base;
0455     }
0456   }
0457  
0458   return(ret_code);
0459 }
0460  
0461  
0462 /******************************************************************
0463 *  Function: MemTestDevice
0464 *
0465 *  Purpose: Tests that every bit in the memory device within the 
0466 *           specified address range can store both a '1' and a '0'.
0467 *
0468 ******************************************************************/
0469 static int MemTestDevice(unsigned int memory_base, unsigned int nBytes)
0470 {
0471   unsigned int offset;
0472   unsigned int pattern;
0473   unsigned int antipattern;
0474   unsigned int ret_code = 0x0;
0475  
0476   /* Fill memory with a known pattern. */
0477   for (pattern = 1, offset = 0; offset < nBytes; pattern++, offset+=4)
0478   {
0479     IOWR_32DIRECT(memory_base, offset, pattern);
0480   }
0481  
0482   printf(" .");
0483  
0484   /* Check each location and invert it for the second pass. */
0485   for (pattern = 1, offset = 0; offset < nBytes; pattern++, offset+=4)
0486   {
0487     if (IORD_32DIRECT(memory_base, offset) != pattern)
0488     {
0489       ret_code = (memory_base + offset);
0490       break;
0491     }
0492     antipattern = ~pattern;
0493     IOWR_32DIRECT(memory_base, offset, antipattern);
0494   }
0495  
0496   printf(" .");
0497  
0498   /* Check each location for the inverted pattern and zero it. */
0499   for (pattern = 1, offset = 0; offset < nBytes; pattern++, offset+=4)
0500   {
0501     antipattern = ~pattern;
0502     if (IORD_32DIRECT(memory_base, offset) != antipattern)
0503     {
0504       ret_code = (memory_base + offset);
0505       break;
0506     }
0507     IOWR_32DIRECT(memory_base, offset, 0x0);
0508   }
0509   return ret_code;
0510 }
0511  
0512 /******************************************************************
0513 *  Function: dma_done
0514 *
0515 *  Purpose: Called when a DMA recieve transaction is complete.
0516 *           Increments rx_done to signal to the main program that
0517 *           the transaction is done.
0518 *
0519 ******************************************************************/
0520 #ifdef DMA_NAME  
0521 static void dma_done (void* handle, void* data)
0522 {
0523   rx_done++;
0524 }
0525 #endif /* DMA_NAME */  
0526  
0527 /******************************************************************
0528 *  Function: MemDMATest
0529 *
0530 *  Purpose: Tests every bit in the memory device within the 
0531 *  specified address range using DMA.  The DMA controller provides 
0532 *  a more rigourous test of the memory since it performs back-to-
0533 *  back memory accesses at full system speed.
0534 *
0535 ******************************************************************/
0536 #ifdef DMA_NAME  
0537 static int MemDMATest(unsigned int memory_base, unsigned int nBytes)
0538 {
0539   int rc;
0540   int ret_code = 0;
0541   int pattern, offset;
0542   alt_dma_txchan txchan;
0543   alt_dma_rxchan rxchan;
0544   void* data_written;
0545   void* data_read;
0546    
0547   /* Get a couple buffers for the test */
0548   data_written = (void*)alt_uncached_malloc(0x1000);
0549   data_read = (void*)alt_uncached_malloc(0x1000);
0550    
0551    
0552   /* Fill write buffer with known values */
0553   for (pattern = 1, offset = 0; offset < 0x1000; pattern++, offset+=4)
0554   {
0555     IOWR_32DIRECT((int)data_written, offset, pattern);
0556   }
0557  
0558   /* Create the transmit channel */
0559   if ((txchan = alt_dma_txchan_open("/dev/dma")) == NULL)
0560   {
0561     printf ("Failed to open transmit channel\n");
0562     exit (1);
0563   }
0564    
0565   /* Create the receive channel */
0566   if ((rxchan = alt_dma_rxchan_open("/dev/dma")) == NULL)
0567   {
0568     printf ("Failed to open receive channel\n");
0569     exit (1);
0570   }
0571    
0572   for(offset = memory_base; offset < (memory_base + nBytes); offset += 0x1000)
0573   {
0574     /* Use DMA to transfer from write buffer to memory under test */
0575     /* Post the transmit request */
0576     if ((rc = alt_dma_txchan_send (txchan, data_written, 0x1000, NULL, NULL)) < 0)
0577     {
0578       printf ("Failed to post transmit request, reason = %i\n", rc);
0579       exit (1);
0580     }
0581  
0582     /* Post the receive request */
0583     if ((rc = alt_dma_rxchan_prepare (rxchan, (void*)offset, 0x1000, dma_done, NULL)) < 0)
0584     {
0585       printf ("Failed to post read request, reason = %i\n", rc);
0586       exit (1);
0587     }
0588    
0589     /* Wait for transfer to complete */
0590     while (!rx_done);
0591     rx_done = 0;
0592      
0593     /* Clear the read buffer before we fill it */
0594     memset(data_read, 0, 0x1000);
0595      
0596     /* Use DMA to read data back into read buffer from memory under test */
0597     /* Post the transmit request */
0598     if ((rc = alt_dma_txchan_send (txchan, (void*)offset, 0x1000, NULL, NULL)) < 0)
0599     {
0600       printf ("Failed to post transmit request, reason = %i\n", rc);
0601       exit (1);
0602     }
0603  
0604     /* Post the receive request */
0605     if ((rc = alt_dma_rxchan_prepare (rxchan, data_read, 0x1000, dma_done, NULL)) < 0)
0606     {
0607       printf ("Failed to post read request, reason = %i\n", rc);
0608       exit (1);
0609     }
0610  
0611     /* Wait for transfer to complete */
0612     while (!rx_done);
0613     rx_done = 0;
0614      
0615     if (memcmp(data_written, data_read, 0x1000))
0616     {
0617       ret_code = offset;
0618       break;
0619     }
0620   }
0621   alt_uncached_free(data_written);
0622   alt_uncached_free(data_read);
0623   return ret_code;
0624 }
0625 #endif /* DMA_NAME */  
0626  
0627  
0628 /******************************************************************
0629 *  Function: TestRam
0630 *
0631 *  Purpose: Performs a full-test on the RAM specified.  The tests
0632 *           run are:
0633 *             - MemTestDataBus
0634 *             - MemTestAddressBus
0635 *             - MemTest8_16BitAccess
0636 *             - MemTestDevice
0637 *             - MemDMATest
0638 *
0639 ******************************************************************/
0640 static void TestRam(void)
0641 {
0642    
0643   int memory_base, memory_end, memory_size;
0644   int ret_code = 0x0;
0645  
0646   /* Find out what range of memory we are testing */
0647   MemGetAddressRange(&memory_base, &memory_end);
0648   memory_size = (memory_end - memory_base);
0649  
0650   printf("\n");
0651   printf("Testing RAM from 0x%X to 0x%X\n", memory_base, (memory_base + memory_size));
0652  
0653   /* Test Data Bus. */
0654   ret_code = MemTestDataBus(memory_base);
0655  
0656   if (ret_code)
0657    printf(" -Data bus test failed at bit 0x%X", (int)ret_code);
0658   else
0659     printf(" -Data bus test passed\n");
0660  
0661   /* Test Address Bus. */
0662   if (!ret_code)
0663   {
0664     ret_code  = MemTestAddressBus(memory_base, memory_size);
0665     if  (ret_code)
0666       printf(" -Address bus test failed at address 0x%X", (int)ret_code);
0667     else
0668       printf(" -Address bus test passed\n");
0669   }
0670  
0671   /* Test byte and half-word access. */
0672   if (!ret_code)
0673   {
0674     ret_code = MemTest8_16BitAccess(memory_base);
0675     if  (ret_code)
0676       printf(" -Byte and half-word access test failed at address 0x%X", (int)ret_code);
0677     else
0678       printf(" -Byte and half-word access test passed\n");
0679   }
0680  
0681   /* Test that each bit in the device can store both 1 and 0. */
0682   if (!ret_code)
0683   {
0684     printf(" -Testing each bit in memory device.");
0685     ret_code = MemTestDevice(memory_base, memory_size);
0686     if  (ret_code)
0687       printf("  failed at address 0x%X", (int)ret_code);
0688     else
0689       printf("  passed\n");
0690   }
0691    
0692   /* Test DMA access to the RAM if DMA exists */
0693 #ifdef DMA_NAME  
0694   if (!ret_code)
0695   {
0696     printf(" -Testing memory using DMA.");
0697     ret_code = MemDMATest(memory_base, memory_size);
0698     if  (ret_code)
0699       printf("  failed at address 0x%X", (int)ret_code);
0700     else
0701       printf("  passed\n");
0702   }
0703 #endif /* DMA_NAME */
0704        
0705   if (!ret_code)
0706     printf("Memory at 0x%X Okay\n", memory_base);
0707 }
0708  
0709  
0710 /******************************************************************
0711 *  Function: FlashCheckIfBlockErased
0712 *
0713 *  Purpose: Checks the specified flash block to see if it is 
0714 *           completely erased (all 0xFFFFFFFF).
0715 *
0716 ******************************************************************/
0717 static int FlashCheckIfBlockErased(alt_flash_fd* fd, int block, flash_region* regions)
0718 {
0719   int i, j;
0720   int ret_code = 0x0;
0721   char block_is_erased = 0x1;
0722   alt_u8 *data_read;
0723   
0724   /* Get a buffer */
0725   data_read = malloc(64);
0726    
0727   /* Initialize the flag */
0728   block_is_erased = 0x1;
0729  
0730   for(i = 0; i < regions->block_size; i += 64)
0731   {
0732     ret_code = alt_read_flash(fd, ((block * regions->block_size) + i), data_read, 64);
0733  
0734     for(j=0; j < 64; j+=1)
0735     {
0736       if(*(data_read+j) != 0xFF)
0737       {
0738         /* If this byte isn't erased, then neither is the block */
0739         block_is_erased = 0x0;
0740         break;
0741       }
0742     }
0743     if (block_is_erased == 0x0)
0744       break;
0745   }
0746   /* Block is erased if we indexed through all block locations */
0747   if(i == regions->block_size)
0748     ret_code = 1;
0749   else
0750     ret_code = 0;
0751    
0752   free(data_read);
0753   
0754   return ret_code;
0755 }
0756  
0757  
0758 /******************************************************************
0759 *  Function: FlashTestBlockWrite
0760 *
0761 *  Purpose: Tests that the function alt_write_flash_block is
0762 *           is working properly.
0763 *
0764 ******************************************************************/
0765 static int FlashTestBlockWrite(int block, int *error, alt_flash_fd* fd, flash_region* regions)
0766 {
0767   int i;
0768   int ret_code = 0x0;
0769   int test_offset;
0770  
0771   alt_u8 *data_written;
0772   alt_u8 *data_read;
0773  
0774  
0775   /* Get a couple buffers for the test */
0776   data_written = malloc(100);
0777   data_read = malloc(100);
0778  
0779   test_offset = (regions->offset + (block * regions->block_size));
0780  
0781   /* Fill write buffer with 100 values (incremented by 3) */
0782   for(i=0; i < 100; i++)
0783     *(data_written + i) = (i * 3);
0784  
0785   /* Write the buffer to flash starting 0x40 bytes from the beginning of the block. */
0786   printf(" -Testing \"alt_write_flash_block\".");
0787   ret_code = alt_write_flash_block(fd, test_offset, (test_offset + 0x40), data_written, 100);
0788   if (!ret_code)
0789   {
0790     /* Now read it back into the read_buffer */
0791     ret_code = alt_read_flash(fd, (test_offset + 0x40), data_read, 100);
0792     if(!ret_code)
0793     {
0794       /* See if they match */
0795       if (memcmp(data_written, data_read, 100))
0796       {
0797         printf("  FAILED.\n");
0798         *error++;
0799       }
0800       else
0801         printf("  passed.\n");
0802     }
0803   }
0804  
0805   /* Test unaligned writes */
0806   if(!ret_code)
0807   {
0808     /* Erase the block */
0809     ret_code = alt_erase_flash_block(fd, test_offset, regions->block_size);
0810    
0811     /* Write the buffer to flash on an unaligned address. */
0812     printf(" -Testing unaligned writes.");
0813     ret_code = alt_write_flash_block(fd, test_offset, (test_offset + 0x43), data_written, 100);
0814     if (!ret_code)
0815     {
0816       /* Now read it back into the read_buffer */
0817       ret_code = alt_read_flash(fd, (test_offset + 0x43), data_read, 100);
0818       if(!ret_code)
0819       {
0820         /* See if they match */
0821         if (memcmp(data_written, data_read, 100))
0822         {
0823           printf("  FAILED.\n");
0824           *error++;
0825         }
0826         else
0827           printf("  passed.\n");
0828       }
0829     }
0830   }
0831  
0832   /* Free up the buffers we allocated. */
0833   free(data_written);
0834   free(data_read);
0835    
0836   return ret_code;
0837 }
0838  
0839  
0840 /******************************************************************
0841 *  Function: FlashTestReadWrite
0842 *
0843 *  Purpose: Tests that the functions alt_write_flash and
0844 *           alt_read_flash are working properly, as well as tests
0845 *           that every bit in the specified block can store both
0846 *           a '1' and '0'.
0847 *
0848 ******************************************************************/
0849 static int FlashTestReadWrite(int block, int *error, alt_flash_fd* fd, flash_region* regions)
0850 {
0851   int i;
0852   int ret_code = 0x0;
0853   int test_offset;
0854  
0855   alt_u8 *data_written;
0856   alt_u8 *data_read;
0857   
0858  
0859   /* Get a couple buffers for the tests */
0860   data_written = malloc(regions->block_size);
0861   data_read = malloc(regions->block_size);
0862   
0863   /* Calculate the offset at which the block lives */
0864   test_offset = (regions->offset + (block * regions->block_size));
0865  
0866   printf("\n -Starting Flash Test.\n");
0867   
0868   printf(" -Testing \"alt_write_flash\" and \"alt_read_flash\".\n");
0869   /* Fill buffer with incrementing values */
0870   for(i=0; i < regions->block_size; i++)
0871     *(data_written + i) = i;
0872  
0873   /* Write the buffer to flash block */
0874   ret_code = alt_write_flash(fd, test_offset, data_written, regions->block_size);
0875       
0876   if (!ret_code)
0877   {
0878     /* Read flash block into read buffer */
0879     ret_code = alt_read_flash(fd, test_offset, data_read, regions->block_size);
0880     if(!ret_code)
0881     {
0882       /* See if they match */
0883       if (memcmp(data_written, data_read, regions->block_size))
0884       {
0885         printf("    pass 1 - FAILED.\n");
0886         *error++;
0887       }
0888       else
0889         printf("    pass 1 - passed.\n");
0890     }
0891    
0892     /* Now fill the buffer with decrementing values (invert the incrementing ones) */
0893     for(i=0; i < regions->block_size; i++)
0894       *(data_written + i) = ~((alt_u8)(i));
0895   
0896     /* Write the buffer to flash block */
0897     ret_code = alt_write_flash(fd, test_offset, data_written, regions->block_size);
0898      
0899     if (!ret_code)
0900     {
0901       /* Read flash block into read buffer */
0902       ret_code = alt_read_flash(fd, test_offset, data_read, regions->block_size);
0903       if(!ret_code)
0904       {
0905         /* See if they match */
0906         if (memcmp(data_written, data_read, regions->block_size))
0907         {
0908           printf("    pass 2 - FAILED.\n");
0909           *error++;
0910         }
0911         else
0912           printf("    pass 2 - passed.\n");
0913       }
0914     }
0915     if (*error)
0916       ret_code = 1;
0917   }
0918  
0919   /* Free up the buffers we allocated */
0920   free(data_written);
0921   free(data_read);
0922    
0923   return ret_code;
0924 }
0925  
0926  
0927 /******************************************************************
0928 *  Function: FlashTestBlockErase
0929 *
0930 *  Purpose: Tests that the function alt_erase_flash_block is
0931 *           is working properly.  Assumes that the specified
0932 *           flash block contains some non-0xFFFFFFFF data before
0933 *           this function is called.
0934 *
0935 ******************************************************************/
0936 static int FlashTestBlockErase(int block, int *error, alt_flash_fd* fd, flash_region* regions)
0937 {
0938  
0939   int ret_code = 0x0;
0940   int test_offset;
0941  
0942   /* Calculate the offset of the block */
0943   test_offset = (regions->offset + (block * regions->block_size));
0944  
0945   printf(" -Testing \"alt_erase_flash_block\".");
0946   ret_code = alt_erase_flash_block(fd, test_offset, regions->block_size);
0947   /* Check that the erase was successful. */
0948   if (!ret_code)
0949   {
0950     if(FlashCheckIfBlockErased(fd, block, regions))
0951       printf("  passed.\n");
0952     else
0953     {
0954       printf("  FAILED\n");  
0955       *error++;
0956     }
0957   }
0958    
0959   return ret_code;
0960 }
0961  
0962  
0963 /******************************************************************
0964 *  Function: FlashRunTests
0965 *
0966 *  Purpose: Performs a full-test on the Flash specified.  The tests
0967 *           run are:
0968 *             - alt_write_flash
0969 *             - alt_read_flash
0970 *             - alt_erase_flash_block
0971 *             - alt_write_flash_block
0972
0973 ******************************************************************/
0974 static void FlashRunTests(alt_flash_fd* fd, int block, flash_region* regions)
0975 {
0976   int ret_code = 0x0;
0977   int error = 0x0;
0978   int test_offset;
0979  
0980   /* Calculate the offset of the block */
0981   test_offset = (regions->offset + (block * regions->block_size));
0982    
0983   /* Test reading and writing functions */
0984   ret_code = FlashTestReadWrite(block, &error, fd, regions);
0985   
0986   /* Test the erase function */
0987   if (!ret_code)
0988   {
0989     ret_code = FlashTestBlockErase(block, &error, fd, regions);
0990   }
0991   /* Test the block write function */
0992   if (!ret_code)
0993   {
0994     ret_code = FlashTestBlockWrite(block, &error, fd, regions);
0995   }
0996  
0997   /* Erase the block so we dont fill one up each time we run the test */
0998   printf(" -Returning block %d to its erased state.\n", block);
0999   alt_erase_flash_block(fd, test_offset, regions->block_size);
1000   
1001   printf(" -Flash tests complete.\n");
1002   if(ret_code || error)
1003   {
1004     printf(" -At least one test failed.\n\n");
1005   }
1006 }
1007  
1008  
1009 /******************************************************************
1010 *  Function: GetFlashName
1011 *
1012 *  Purpose: Gets the name of the flash to test from the user
1013 *           Defaults to "/dev/ext_flash", the name of the flash
1014 *           component in the Nios II example designs.
1015
1016 ******************************************************************/
1017 static int GetFlashName(char line[30], int flash_type)
1018 {
1019  
1020   char ch = 0x0;
1021   int i;
1022  
1023   if (flash_type == CFI)
1024   
1025     printf("\nEnter the name of the CFI flash device to be opened,\n");
1026     printf("or just press <ENTER> to open \"/dev/ext_flash\"\n");
1027     printf(">");
1028   }
1029   else if (flash_type == EPCS)
1030   {
1031     printf("\nEnter the name of the EPCS flash device to be opened,\n");
1032     printf("or just press <ENTER> to open \"/dev/epcs_controller\"\n");
1033     printf(">");
1034   }
1035   
1036   for(i = 0; ch != '\n'; i++)
1037   {
1038     ch = getc(stdin);
1039     if(ch == '\r' || ch == '\n')
1040     {
1041       /* Hitting <ENTER> defaults to the standard component name */
1042       if( i <= 1 )
1043       {
1044         if (flash_type == CFI)
1045           strcpy(line, "/dev/ext_flash\0");
1046         else if (flash_type == EPCS)
1047           strcpy(line, "/dev/epcs_controller\0");
1048       }
1049           
1050       else
1051         /* Properly terminate the string. */
1052         line[i] = '\0';
1053     }
1054     else
1055      line[i] = ch;
1056   }
1057   
1058   return 0;
1059 }
1060  
1061  
1062  
1063 /******************************************************************
1064 *  Function: FlashErase
1065 *
1066 *  Purpose: Erases 1 or all blocks in the specified flash device.
1067
1068 ******************************************************************/
1069 static void FlashErase(int flash_type)
1070 {
1071   alt_flash_fd* fd;
1072   int test_offset;
1073   int ret_code;
1074   flash_region* regions;
1075   int number_of_regions;
1076   alt_u8 entry[4];
1077   alt_u8 flashname[30];
1078   unsigned int block;
1079   
1080   /* Get the name of the flash we are erasing */
1081   ret_code = GetFlashName(flashname, flash_type);
1082   
1083   fd = alt_flash_open_dev(flashname);
1084   if (fd)
1085   {
1086     /* Find out some useful stuff about the flash */
1087     ret_code = alt_get_flash_info(fd, ®ions, &number_of_regions);
1088     if (!ret_code)
1089     {
1090       printf(" -Region has %d blocks.\n", regions->number_of_blocks);
1091       printf(" -Which block would you like to erase?\n");
1092       printf(" -> ");
1093        
1094       GetInputString( entry, sizeof(entry), stdin );
1095  
1096       if(entry[0] == 'a')
1097       {
1098         printf(" -Erase ALL blocks? (y/n) ");
1099  
1100         GetInputString( entry, sizeof(entry), stdin );
1101          
1102         if(entry[0] == 'y')
1103         {
1104           /* Erase all blocks */
1105           printf(" -Erasing %d blocks.  Please Wait.\n", (regions->number_of_blocks));
1106           for(block = 0; block < regions->number_of_blocks; block++)
1107           {
1108             /* Dont erase it if it's already erased silly. */
1109             if ((FlashCheckIfBlockErased(fd, block, regions)) == 0)
1110             {
1111               test_offset = (regions->offset + (block * regions->block_size));
1112               alt_erase_flash_block(fd, test_offset, regions->block_size);
1113             }
1114             /* Just a simple progress meter so we dont get bored waiting for the flash to erase. */
1115             printf(".");
1116             if(((block + 1) % 80) == 0)
1117             {
1118               printf("\n");
1119             }
1120           }
1121           printf("\n -All Blocks Erased.\n");
1122         }
1123         else
1124         {
1125           printf("Erased zero blocks.\n");
1126         }
1127       }
1128       /* Just erase one block */
1129       if(sscanf(entry, "%d\n", &block))
1130       {
1131         if ((block >= 0) && (block <= (regions->number_of_blocks - 1)))
1132         {
1133           test_offset = (regions->offset + (block * regions->block_size));
1134           alt_erase_flash_block(fd, test_offset, regions->block_size);
1135           printf(" -Block %d erased.\n", block);
1136         }
1137         else
1138         {
1139           printf(" -Block number entered is %d\n", block);
1140           printf(" -Block number must be between 0 and %d.\n", (regions->number_of_blocks - 1));
1141         }
1142       }
1143     }
1144     printf(" -Closing flash \"%s\".\n", flashname);
1145     alt_flash_close_dev(fd);
1146   }
1147 }
1148  
1149    
1150 /******************************************************************
1151 *  Function: FlashFindErasedBlocks
1152 *
1153 *  Purpose: Looks through the specified flash for blocks which 
1154 *           are completely erased.  If the mode parameter is 
1155 *           TEST, this function simply returns the index of the 
1156 *           first block which is completely erased.  If the mode
1157 *           parameter is SHOWMAP, the function prints a list of 
1158 *           all blocks, indicating which ones are erased.
1159
1160 ******************************************************************/
1161 static int FlashFindErasedBlocks(alt_flash_fd* fd, flash_region* regions, int number_of_regions, int mode)
1162
1163   int region_index, block_index;
1164   int block_erased = 0x0;
1165   alt_u8 entry[5];
1166   unsigned int block;
1167  
1168   /* Currently only supports flashes with 1 region, but region loop is left here for possible */
1169   /* future implementation */
1170   for(region_index = 0; region_index < number_of_regions; region_index++)
1171   {
1172     printf(" -Checking Region %d for erased blocks.\n", region_index);
1173     /* SHOWMAP mode has a legend reminding us what little plus and minus signs mean */
1174     if(mode == SHOWMAP)
1175     {
1176       printf("            erased block = '-'\n");     
1177       printf("          unerased block = '+'\n\n");     
1178     }
1179     /* Check those blocks. */
1180     for(block_index = 0; block_index < (regions->number_of_blocks); block_index++)
1181     {
1182       block_erased = FlashCheckIfBlockErased(fd, block_index, regions);
1183       /* If it's erased and were running in TEST mode, we're done */
1184       if(block_erased && (mode == TEST))
1185         break;
1186       /* If in SHOWMAP mode, mark block as either erased or not-erased. */
1187       else if(block_erased && (mode == SHOWMAP))
1188         printf("  Block %3d @ 0x%8.8X:\t-\n", block_index, (regions->offset + (block_index * regions->block_size)));           
1189       else if(!block_erased && (mode == SHOWMAP))
1190         printf("  Block %3d @ 0x%8.8X:\t+\n", block_index, (regions->offset + (block_index * regions->block_size)));           
1191     }
1192     /* Special case if no blocks are erased (TEST mode only)*/
1193     if(( block_index == ( regions->number_of_blocks )) && ( mode == TEST ))
1194     {
1195       printf(" -Found no erased blocks.  Please enter the number of the block\n");
1196       printf("  you would like to test.  Enter 'q' to quit without testing flash.\n");
1197       printf(" -> ");
1198  
1199       GetInputString( entry, sizeof(entry), stdin );
1200  
1201       if(entry[0] == 'q')
1202       {
1203             block_index = QUIT_WITHOUT_TESTING;
1204             break;
1205         }
1206       else if(sscanf(entry, "%d\n", &block))
1207       {
1208         if ((block >= 0) && (block <= (regions->number_of_blocks - 1)))
1209         {
1210             block_index = block;
1211             break;
1212         }
1213         else
1214         {
1215           printf(" -Block number entered is %d\n", block);
1216           printf(" -Block number must be between 0 and %d.\n", (regions->number_of_blocks - 1));
1217         }
1218       }        
1219     }
1220     /* Break out of the region loop if we've found an erased block to test. */
1221     if(block_erased && (mode == TEST))
1222       break;
1223   }
1224  
1225   return block_index;
1226 }
1227  
1228  
1229 /******************************************************************
1230 *  Function: TestFlash
1231 *
1232 *  Purpose: Opens the specified flash device.  If the mode
1233 *           parameter is TEST, the function finds an erased 
1234 *           block, then tests it.  If the mode parameter is 
1235 *           SHOWMAP, the function lists all blocks in the flash and
1236 *           indicates which ones are erased.  The flash is closed
1237 *           at the end of the function.
1238
1239 ******************************************************************/
1240 static void TestFlash(int mode, int flash_type)
1241 {
1242   alt_flash_fd* fd;
1243   int number_of_regions;
1244   int block;
1245   flash_region* regions;
1246   int ret_code = 0x0;
1247   alt_u8 entry[4];
1248   alt_u8 flashname[30];
1249    
1250   ret_code = GetFlashName(flashname, flash_type);
1251  
1252   fd = alt_flash_open_dev(flashname);
1253   if (fd)
1254   {
1255     printf(" -Successfully opened %s\n", flashname);
1256      
1257     /* Get some useful info about the flash */
1258     ret_code = alt_get_flash_info(fd, ®ions, &number_of_regions);
1259        
1260     if (!ret_code)
1261     {
1262       printf(" -Region 0 contains %d blocks.\n", regions->number_of_blocks);
1263        
1264       block = FlashFindErasedBlocks(fd, regions, number_of_regions, mode);
1265  
1266       /* If we're in TEST mode, ask if this block is okay to test. */
1267       if(( mode == TEST ) && ( block != QUIT_WITHOUT_TESTING ))
1268       {
1269         printf(" -Block %d, at address 0x%X identified.\n", block, (regions->offset + (block * regions->block_size)));
1270         printf(" -Would you like to test this block? (y/n)");
1271  
1272         GetInputString(entry, sizeof(entry), stdin);
1273  
1274         if ( entry[0] == 'y' && entry[1] == '\n' )
1275         {
1276           /* Test that Flash! */
1277           FlashRunTests(fd, block, regions);
1278           printf(" -Closing flash device \"%s\".\n", flashname);
1279           alt_flash_close_dev(fd);
1280         }       
1281       }
1282     }
1283   }
1284   else
1285   {
1286     printf(" -ERROR: Could not open %s\n", flashname);   
1287   }
1288 }
1289  
1290  
1291 /******************************************************************
1292 *  Function: TopMenu
1293 *
1294 *  Purpose: Generates the top level menu.
1295
1296 ******************************************************************/
1297 static int TopMenu( void )
1298 {
1299   char ch;
1300  
1301   /* Print the top-level menu to stdout */
1302   while (1)
1303   {
1304     MenuBegin("      Memory Test Main Menu");
1305     MenuItem( 'a', "Test RAM" );
1306     MenuItem( 'b', "Test Flash");
1307 #ifdef EPCS_CONTROLLER_NAME    
1308     MenuItem( 'c', "Test EPCS Serial Flash");
1309     ch = MenuEnd( 'a', 'c' );    
1310 #else
1311     ch = MenuEnd( 'a', 'b' );
1312 #endif /* EPCS_CONTROLLER_NAME */
1313  
1314     switch(ch)
1315     {
1316       MenuCase('a',TestRam());
1317       MenuCase('b',TestFlash(TEST, CFI));
1318       MenuCase('e',FlashErase(CFI));       /* hidden option */
1319       MenuCase('m',TestFlash(SHOWMAP, CFI)); /* hidden option */
1320 #ifdef EPCS_CONTROLLER_NAME    
1321       MenuCase('c',TestFlash(TEST, EPCS));
1322       MenuCase('f',FlashErase(EPCS));       /* hidden option */
1323       MenuCase('s',TestFlash(SHOWMAP, EPCS)); /* hidden option */
1324 #endif /* EPCS_CONTROLLER_NAME */
1325       case 'q':    break;
1326       default:    printf("\n -ERROR: %c is an invalid entry.  Please try again\n", ch); break;
1327     }
1328     if (ch == 'q')
1329       break;
1330     printf("\nPress enter to continue...\n");
1331     while( (( ch = getc(stdin)) != '\n' ) && ( ch != EOF ));
1332  
1333   }
1334   return (ch);
1335 }
1336  
1337  
1338 /******************************************************************
1339 *  Function: main
1340 *
1341 *  Purpose: Continually prints the menu and performs the actions
1342 *           requested by the user.
1343
1344 ******************************************************************/
1345 int main(void)
1346 {
1347  
1348   int ch;
1349  
1350   /* Print the Header */
1351   MenuHeader();
1352   /* Print the menu and do what the user requests, until they hit 'q' */
1353   while (1)
1354   {
1355     ch = TopMenu();
1356     if (ch == 'q')
1357     {
1358       printf( "\nExiting from Memory Test.\n");
1359       break;
1360     }
1361   }
1362   return (0);
1363 }
1364  
1365  
1366 /******************************************************************************
1367 *                                                                             *
1368 * License Agreement                                                           *
1369 *                                                                             *
1370 * Copyright (c) 2004 Altera Corporation, San Jose, California, USA.           *
1371 * All rights reserved.                                                        *
1372 *                                                                             *
1373 * Permission is hereby granted, free of charge, to any person obtaining a     *
1374 * copy of this software and associated documentation files (the "Software"),  *
1375 * to deal in the Software without restriction, including without limitation   *
1376 * the rights to use, copy, modify, merge, publish, distribute, sublicense,    *
1377 * and/or sell copies of the Software, and to permit persons to whom the       *
1378 * Software is furnished to do so, subject to the following conditions:        *
1379 *                                                                             *
1380 * The above copyright notice and this permission notice shall be included in  *
1381 * all copies or substantial portions of the Software.                         *
1382 *                                                                             *
1383 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  *
1384 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    *
1385 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
1386 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      *
1387 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING     *
1388 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER         *
1389 * DEALINGS IN THE SOFTWARE.                                                   *
1390 *                                                                             *
1391 * This agreement shall be governed in all respects by the laws of the State   *
1392 * of California and by the laws of the United States of America.              *
1393 * Altera does not recommend, suggest or require that this reference design    *
1394 * file be used in conjunction or combination with any other product.          *
1395 ******************************************************************************/

参考

1. Altera.Nios II Software Developer's Handbook