/*****************************************************************************
*  File: custom_boot_copier.c
*
*  This is an example of a custom Nios II boot copier implemented in C. 
*  The boot copier can be built and run from Nios II IDE.  For instructions
*  on how to build and run this boot copier, refer to the application note
*  that accompianies it.
*
*  Feel free to customize this boot copier, but do so at your own risk.  This
*  boot copier can only be supported by Altera in its current, unmodified form

*****************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "advanced_boot_copier.h"
#include "system.h"
#include "alt_types.h"
#include "sys/alt_alarm.h"
#include "sys/alt_cache.h"
#include "sys/alt_dev.h"
#include "sys/alt_irq.h"
#include "sys/alt_sys_init.h"
#include "priv/alt_file.h"
#include "altera_avalon_pio_regs.h"
#include "altera_avalon_jtag_uart_regs.h"
#include "altera_avalon_jtag_uart.h"

/*
 * Edit this define to turn on or turn off the JTAG UART during boot
 */
#define USING_JTAG_UART 0

/*
 * This example prints a lot of information, this macro is intended to make the
 * code a bit easier to read.  If you do not wish to print anything during boot,
 * change the define at the top of this file to "#define USING_JTAG_UART 0"
 */
#if USING_JTAG_UART

# define JTAGPRINT(name) MyJtagWrite(name, sizeof(name)-1)
# define JTAG_UART_TIMEOUT   ( alt_ticks_per_second() * 2 ) // 2 seconds
# define JTAG_WAITING_BIT   (1 << 1)
# define JTAG_ABANDONED_BIT (1 << 2)

  // Stores the transmit state of the JTAG_UART
  volatile alt_u32 jtag_uart_state;

  // Prototypes for our JTAG UART printing functions
  int MyJtagWrite(const char *buf, int len);
  int MyJtagWrite8(const char *buf, int len);

#endif //USING_JTAG_UART


/*
 * The following statement defines "main()" so that when the Nios II SBT4E
 * debugger is set to break at "main()", it will break at the appropriate
 * place in this program, which does not contain a function called "main()".
*/
int main (void) __attribute__ ((weak, alias ("alt_main")));

/*****************************************************************************
*  Function: alt_main
*
*  Purpose: This is our boot copier's entry point. We are implementing
*  this as an alt_main() instead of a main(), so that we can better control
*  the drivers that load and the system resources that are enabled.  Since
*  code size may be a consideration, this method allows us to keep the
*  memory requirements small.
*
*****************************************************************************/
int alt_main(void)
{
  /*
   * Define the local variables used by this function.
   */
  alt_u32 entry_point;
 
  /*
   * Define the strings used in this function for printing out STDOUT.  The
   * purpose of this is to avoid using the potentially large printf C library.
   */
# if USING_JTAG_UART

      char stars_str[] = "****************************************\n";
      char hello_str0[] = "  Example Custom Boot Copier Starting\n     Booting EPCS from On-Chip RAM \n\n";
      char hello_str1[] = "\nThis copier finds application images\n after .pof in EPCS memory.\n";


    char boot_proceed_str[] = "\nNow attempting to boot.\n";
    char reset_str[] = "\nNow jumping back to reset vector.\n";
    char no_image_str[] = "\nNo valid application image found in\nflash memory.\n";
    char jumping_str[] = "\nNow attempting to load and jump to the\napplication.\n\n";

    // Initialize the STDIO defaults as selected in the Nios II IDE. 
    alt_io_redirect (ALT_STDOUT, ALT_STDIN, ALT_STDERR);
    jtag_uart_state = 0x1;

# endif // USING_JTAG_UART

  /*
   * Perform system initialization.  Since our entry point is alt_main instead
   * of simply main, it's our responsibility to initialize any drivers we
   * wish to use.  An example of how to do this can be found in the
   * hello_world freestanding demo.
   */

  /*
   * In order to allow interrupts to occur while the boot copier executes we
   * initialize the main irq handler.
   */
  alt_irq_init (ALT_IRQ_BASE);
 
  /*
   * Now we initialize the drivers that we require.
   */
  alt_sys_init();

  /*
   * If you intend to print anything during boot, you'll need to initialize
   * the STDIO defaults as selected in the Nios II IDE.  If you dont need
   * to print anything during boot, you can comment out this line.
   */
# if USING_JTAG_UART
    alt_io_redirect (ALT_STDOUT, ALT_STDIN, ALT_STDERR);
    jtag_uart_state = 0x1;
# endif  // USING_JTAG_UART
 
  /*
   * Now the system is initialized and ready to use.
   *
   * At this point you could start doing whatever you feel necessary.  You could
   * perform diagnostics, validate the hardware environment, communicate with
   * other parts of the system to obtain instructions how to proceed, etc., etc
   *
   * In this example, we'll just turn on an LED, print some basic information
   * to the JTAG UART, and then boot an application from flash.
   */
  
  // Turn on an LED to indicate we are alive
  IOWR_ALTERA_AVALON_PIO_DATA(IOLED_BASE, 0x1);


  /*
   * Print a startup message to let the user see we're alive.
   */
# if USING_JTAG_UART
    JTAGPRINT(stars_str);
    JTAGPRINT(stars_str);
    JTAGPRINT(hello_str0);
    JTAGPRINT(stars_str);
    JTAGPRINT(hello_str1);
    JTAGPRINT(stars_str);
    JTAGPRINT(stars_str);

# endif  //USING_JTAG_UART

  /*
   * Now we begin the boot process.
   */
 
  // Print a message to the JTAG UART that we're beginning to boot
#if USING_JTAG_UART

  JTAGPRINT(boot_proceed_str); 

#endif  //USING_JTAG_UART

  /*
   * Pick a flash image to load.  The criteria for picking an image are
   * discussed the text of the application note, and also in the code comments
   * preceeding the function "PickFlashImage()" found in this file.
   */




#if USING_JTAG_UART
      JTAGPRINT(jumping_str);
#endif  //USING_JTAG_UART

    alt_irq_disable_all ();
  
    entry_point = findImage();
    if( entry_point >= 0 )  // load the image
    {
      // Turn on an LED to indicate we are jumping to a valid image.
      IOWR_ALTERA_AVALON_PIO_DATA(IOLED_BASE, 0x2);

      // Jump to the entry point of the application
      JumpFromBootCopier((void(*)(void))(entry_point));
    }
    else
    {
#if USING_JTAG_UART
      // Print which image was picked.
      JTAGPRINT(no_image_str);
#endif  //USING_JTAG_UART

      // Turn on an LED to indicate we are resetting
      IOWR_ALTERA_AVALON_PIO_DATA(IOLED_BASE, 0x4);

      usleep(5000000);
#if USING_JTAG_UART
      // Print which image was picked.
      JTAGPRINT(reset_str);
#endif  //USING_JTAG_UART
      // If the entry point is not found, then we should jump back to the
      // reset vector.
      JumpFromBootCopier((void(*)(void))(NIOS2_RESET_ADDR));
    }
   
  // We should never get here
  exit(0);
}


/*****************************************************************************
*  Function: JumpFromBootCopier
*
*  Purpose: This routine shuts down the boot copier and jumps somewhere else.
*  The place to jump is passed in as a function pointer named "target".
*
*****************************************************************************/
void JumpFromBootCopier(void target(void))
{
  /*
   * If you have any outstanding I/O or system resources that needed to be
   * cleanly disabled before leaving the boot copier program, then this is
   * the place to do that.
   *
   * In this example we only need to ensure the state of the Nios II cpu is
   * equivalent to reset.  If we disable interrupts, and flush the caches,
   * then the program we jump to should receive the cpu just as it would
   * coming out of a hardware reset.
   */
  alt_irq_disable_all ();
  alt_dcache_flush_all ();
  alt_icache_flush_all ();
 
  /*
   * The cpu state is as close to reset as we can get it, so we jump to the new
   * application.
   */
  target();
 
  /*
   * In the odd event that the program we jump to decides to return, we should
   * probably just jump back to the reset vector. We pass in the reset address
   * as a function pointer.
   */
  
  // Turn on an LED to indicate we are resetting
  IOWR_ALTERA_AVALON_PIO_DATA(IOLED_BASE, 0x4);

  // Wait 5 seconds
  usleep(5000000);

  // Jump back to the reset address
  JumpFromBootCopier((void(*)(void))(NIOS2_RESET_ADDR));
}

/*****************************************************************************
*  Function: CopyFromFlash
*
*  Purpose:  This subroutine copies data from a flash memory to a buffer
*  The function uses the appropriate copy routine for the flash that is
*  defined by FLASH_TYPE.  EPCS devices cant simply be read from using
*  memcpy().
*
*****************************************************************************/
void* CopyFromFlash( void * dest, const void * src, size_t num )
{

    // If we're dealing with EPCS, "src" has already been defined for us as
    // an offset into the EPCS, not an absolute address.
    epcs_read_buffer( EPCS_FLASH_CONTROLLER_BASE + EPCS_FLASH_CONTROLLER_REGISTER_OFFSET,
                      (int)src,
                      (alt_u8*)dest,
                      (int)num );
  return (dest);
}


#if USING_JTAG_UART
/*****************************************************************************
*  Function: MyJtagWrite
*
*  Purpose:  This subroutine is provided so that we can write characters out
*  the JTAG UART without getting into a situation where we are permanently
*  blocked, because there is no host reading from the JTAG UART.  So this
*  routine takes the message that we want to write, and breaks it up into
*  8 byte or less chunks to send to MyJtagWrite8().  MyJtagWrite8()
*  makes sure that we can write to the jtag uart before attempting the write.
*
*****************************************************************************/
int MyJtagWrite(const char *buf, int len)
{
  int ret_val;
  int orig_len = len;
 
  if(len > 8)
  {
    // Our write message is greater than 8 bytes long, so break it up into
    // 8-byte or less chunks.
    do
    {
      ret_val = MyJtagWrite8( buf, (len > 8)?(8):(len));
      if(ret_val < 0)
      {
        // If an error returns then we're done
        break;
      }
      else
      {
        // No error, decrement our length, and increment the buffer
        len -= ret_val;
        buf += ret_val;
      }
    } while(len > 0);
   
    // Return the whole length of the buffer transmitted
    ret_val = orig_len;   
  }
  else
  {
    // If the write message is less than 8 bytes, just write it.
    ret_val = MyJtagWrite8( buf, len);
  }
 
  return ret_val;
}


/*****************************************************************************
*  Function: MyJtagWrite8
*
*  Purpose:  This subroutine is called by MyJtagWrite, which feeds it 8-byte
*  or less chunks of data to write out the JTAG UART.  Basically, this routine
*  queries the write fifo in the jtag uart to make sure there is room for our
*  data first.  If there's not room, then it waits JTAG_UART_TIMEOUT seconds
*  to see if a host will clear some of the pending data to allow us to write
*  new data to the fifo.  If no host connects within JTAG_UART_TIMEOUT, then
*  the jtag uart is marked abandoned, and the write data is discarded.  Once
*  abandoned, every time a new write call is made to this routine, it checks
*  to see if a host may have emptied the write fifo, if that ever happens,
*  then the jtag uart is reclaimed and the original algorithm prevails.
*
*****************************************************************************/
int MyJtagWrite8(const char *buf, int len)
{
  alt_fd *the_fd;
  altera_avalon_jtag_uart_dev *the_dev;
  altera_avalon_jtag_uart_state *the_state;
  unsigned int the_base;
  alt_u32 control;
  alt_u32 wr_fifo_space;
  int ret_val;
  alt_alarm my_jtag_uart_alarm;
  volatile alt_u32 my_jtag_uart_context;
 
  /*
   * Look thru the device table to find our device block and extract the base
   * address to this STDOUT peripheral.
   *
   * A big assumption here is that the STDOUT peripheral is a JTAG UART.
   */
  the_fd = &alt_fd_list[STDOUT_FILENO];
  the_dev = (altera_avalon_jtag_uart_dev *)the_fd->dev;
  the_state = (altera_avalon_jtag_uart_state *)&(the_dev->state);
  the_base = the_state->base;

  // Read the jtag uart control register and grab the write fifo space
  control = IORD_ALTERA_AVALON_JTAG_UART_CONTROL(the_base);
  wr_fifo_space = (control & ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK)
                  >> ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_OFST;

  if(wr_fifo_space >= len)
  {
    // The write fifo has room for our write, so clear the abandoned flag
    // and write the message.
    ret_val = write(STDOUT_FILENO, buf, len);
  }
  else
  {
    // The write fifo does not have room for us. have we previously abandoned
    // the jtag uart?
    if( jtag_uart_state & JTAG_ABANDONED_BIT )
    {
      // We have previously abandoned the jtag uart
      if(control & ALTERA_AVALON_JTAG_UART_CONTROL_AC_MSK)
      {
        // There has been activity from a host so let's clear the abandoned
        // flag, and see if the host will clear the fifo for us.
        jtag_uart_state &= ~JTAG_ABANDONED_BIT;
      }
    }
   
    // At this point we check to see if the jtag uart is abandoned
    if( jtag_uart_state & JTAG_ABANDONED_BIT )
    {
      // The jtag uart has been abandoned, so just dump the data and return -1
      ret_val = -1;
    }
    else
    {
      // The jtag uart has not been abandoned
      ret_val = -1;
     
      // Clear the activity bit in the jtag uart control register
      control |= ALTERA_AVALON_JTAG_UART_CONTROL_AC_MSK;
      IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(the_base, control);
     
      // Set a timeout alarm
      my_jtag_uart_context = 0;
      alt_alarm_start (
                        &my_jtag_uart_alarm,          // alt_alarm* alarm,
                        JTAG_UART_TIMEOUT,            // alt_u32 nticks,
                        GenericTimeoutCallback,  // alt_u32 (*callback) (void* context),
                        (void *)&my_jtag_uart_context // void* context
                      );
     
      // Now wait until the timeout occurs and abandon the uart, or the host
      // clears the fifo for us.
      while( my_jtag_uart_context == 0 )
      {
        // Get the current control register value
        control = IORD_ALTERA_AVALON_JTAG_UART_CONTROL(the_base);
       
        if( control & ALTERA_AVALON_JTAG_UART_CONTROL_AC_MSK )
        {
          // We see activity, so stop the timeour alarm
          alt_alarm_stop ( &my_jtag_uart_alarm );
          my_jtag_uart_context = 0;
         
          // Extract the write fifo space
          wr_fifo_space = (control & ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK)
                          >> ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_OFST;
         
          if(wr_fifo_space >= len)
          {
            // We now have room to perform our write, so do it and get outa here
            ret_val = write(STDOUT_FILENO, buf, len);
            break;
          }
          // There's still not enough room so clear the activity bit
          control |= ALTERA_AVALON_JTAG_UART_CONTROL_AC_MSK;
          IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(the_base, control);
         
          // And set the timeout alarm again
          alt_alarm_start (
                            &my_jtag_uart_alarm,          // alt_alarm* alarm,
                            JTAG_UART_TIMEOUT,            // alt_u32 nticks,
                            GenericTimeoutCallback,  // alt_u32 (*callback) (void* context),
                            (void *)&my_jtag_uart_context // void* context
                          );
         
        }
      }
     
      // If we get here, then we're done waiting, so clear the waiting flag
      jtag_uart_state &= ~JTAG_WAITING_BIT;
 
      if( my_jtag_uart_context == 1 )
      {
        // We got here because the timeout alarm fired, so set the abandoned flag
        jtag_uart_state |= JTAG_ABANDONED_BIT;
      }
    }
  }
  return ret_val; 
}


/*****************************************************************************
*  Function: GenericTimeoutCallback
*
*  Purpose:  This subroutine is a generic timeout callback routine for
*  timeout alarms that get set.  This routine simply increments the alt_u32
*  pointed to by the context pointer and returns 0, which requests no
*  additional alarm time.
*
*****************************************************************************/
alt_u32 GenericTimeoutCallback (void* context)
{
  *((volatile alt_u32 *)(context)) += 0x1;
  return(0);
}

#endif  //USING_JTAG_UART


long findImage(void)
{

    alt_u32 r_findp_temp = 0;
    alt_u8 i;
    alt_u8 array[100];
    alt_u32 r_read_byte_return_value;
    CopyFromFlash( (void*)(array), 0, (size_t)(100) );
    for(i=0; i<25; i++)
    {
        r_read_byte_return_value = array[i+48] & 0x20;
        r_read_byte_return_value <<= 26;
        r_findp_temp >>= 1;
        r_findp_temp |= r_read_byte_return_value;
    }
    for(i=0; i<7; i++)
    {
        r_read_byte_return_value = array[i+33] & 0x10;
        r_read_byte_return_value <<= 27;
        r_findp_temp >>= 1;
        r_findp_temp |= r_read_byte_return_value;
    }
//
// Finally, it turns out the length was given in BITS.  Round-up
// to the next byte, and convert to bytes
//
    r_findp_temp += 7;
    r_findp_temp /= 8;
//Now we have begin address program in EPCS

    alt_u32 length;
    alt_u32 address;
    CopyFromFlash( (void*)(&length), (void*)r_findp_temp, (size_t)(4) );
    r_findp_temp += 4;

      // Now loop until we get jump record, or a halt recotd
      while( (length != 0) && (length != 0xffffffff) )
      {
        // Get the next 4 bytes of the boot record, which should be an address
        // record
        CopyFromFlash( (void*)(&address), (void*)r_findp_temp, (size_t)(4) );
        r_findp_temp += 4;


        // Copy the next "length" bytes to "address"
        //if(address != NIOS2_RESET_ADDR)
            CopyFromFlash( (void*)(address), (void*)r_findp_temp, (size_t)(length) );
        r_findp_temp += length;

        // Get the next 4 bytes of the boot record, which now should be another
        // length record
        CopyFromFlash( (void*)(&length), (void*)r_findp_temp, (size_t)(4) );
        r_findp_temp += 4;
      }

      // "length" was read as either 0x0 or 0xffffffff, which means we are done
      // copying.
      if( length == 0xffffffff )
      {
        // We read a HALT record, so return a -1
        return -1;
      }
      else // length == 0x0
      {
        // We got a jump record, so read the next 4 bytes for the entry address
        CopyFromFlash( (void*)(&address), (void*)r_findp_temp, (size_t)(4) );
        r_findp_temp += 4;

        // Return the entry point address
        return address;
      }
}
//return 1 if test ram is Ok
int testRAM(void)
{
    //code of test
    return 0;
}

Конструктор сайтов - uCoz