⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sd_controller.c

📁 在开发FPGA上比较有用
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
*  File:    sd_controller.c
*
*  Purpose: Driver code for the SD Card Controller
*
*  Author: NGK
*
*****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/alt_cache.h>
#include "system.h"
#include "io.h"
#include "sd_controller.h"


sd_card_info_struct* sd_card_global;
sd_commands_struct* sd_cmd;

/*****************************************************************************
*  Function: sd_controller_dev_init
*
*  Purpose: HAL device driver initialization.  Calls the SD Card
*           controller intitialization routine and then registers
*           the filesystem with the HAL.
*           Called by alt_sys_init.
*
*  Returns: 0 -     success
*           non-0 - failure
*
*****************************************************************************/
int sd_controller_dev_init ( sd_controller_dev* sd_dev )
{
  int ret_code = 0;
  int i;
  
  sd_card_global = malloc( sizeof( sd_card_info_struct ));
  if( sd_card_global != NULL )
  {
    // Try to initialize 100 times.  If we fail, then we really did fail.
    for( i = 0; i < 1000; i++ )
    {
        ret_code = sd_controller_init( (unsigned int)sd_dev->base, sd_dev->dev.name );
        if( !ret_code)
        {
            break; 
        }
        usleep( 1000 );
    }
    sd_card_global->init_tries = i + 1;
  }
  else
  {
    ret_code = COULDNT_ALLOC_MEM;
  }
  
  if( !ret_code )
  {
    ret_code = alt_fs_reg( &(sd_dev->dev) );
  }
  else
  {
    sd_card_global->error_code = ret_code;
  }

 
  return ret_code;
}

/*****************************************************************************
*  Function: sd_controller_init
*
*  Purpose: Called by the HAL device driver initialization.  
*           Resets the physical SD Controller, sets up the SD Card
*           clock, and initializes the SD Card.
*
*  Returns: 0 -     success
*           non-0 - failure
*
*****************************************************************************/
int sd_controller_init( unsigned int base_addr, char* mount_point )
{
  
  int ret_code = 0;
  alt_u8 clock_div_value;
  alt_u32 ocr_reg_value;
  
  // Allocate our structures
  sd_cmd = malloc( sizeof( sd_commands_struct ) * 64 );
  
  // Set the name of the SD Card mount point
  strcpy( sd_card_global->mount_point, mount_point );
  
  // Initialize the SD commands
  sd_init_command_struct();  
 
  // Make the controller uncacheable since its register and memory contents can be changed
  // by the controller logic, invalidating the cache.
  base_addr = ( unsigned int )( alt_remap_uncached ( (void*)base_addr, 0x400 ));

  // Set the base address of the SPI controller
  sd_card_global->base_addr = base_addr;
  sd_card_global->data_buff_base_addr = base_addr + SD_DATA_BUFF_OFFSET;
  
  // Reset the controller
  IOWR_32DIRECT( sd_card_global->base_addr, SD_CONTROL_STATUS_OFFSET, SD_SYNC_RESET_BIT_MASK );
  
  // Calculate and write clock divider to start the SPI clock (+1 forces a round-up)
  clock_div_value = (ALT_CPU_FREQ / SD_SPI_MAX_CLK_RATE) + 1;
  IOWR_8DIRECT( sd_card_global->base_addr, SD_CLK_DIV_REG_OFFSET, clock_div_value );
  sd_card_global->max_clk_rate = SD_SPI_MAX_CLK_RATE;
  
  // SD device needs at least 74 clocks before we can issue it any commands
  usleep(( 74 * 1000000 ) / SD_SPI_MAX_CLK_RATE );
  
  // Issue GO_IDLE_STATE command
  ret_code |= sd_sendreceive_spi( sd_card_global, GO_IDLE_STATE, SD_NO_ARG );

  // Issue OP_COND command 
  if( !ret_code )
    ret_code |= sd_sendreceive_spi( sd_card_global, OP_COND, SD_NO_ARG );

  // Issue READ_OCR command
  if( !ret_code )
  {
    ret_code = sd_sendreceive_spi( sd_card_global, READ_OCR, SD_NO_ARG );
    if( !ret_code )
    {
      // Read out OCR value from the controller's response register
      ocr_reg_value = IORD_32DIRECT( sd_card_global->base_addr, SD_COMMAND_RESP0_OFFSET );
  
      // Make sure operating voltages are compatile
      if(( ocr_reg_value & SD_OCR_VOLTAGE_32_36 ) == 0x0 )
        ret_code |= VOLTAGE_NOT_SUPPORTED;  // Does not support voltage range
      
      // Double-check that the busy bit is cleared
      if(( ocr_reg_value & SD_OCR_REG_BUSY_BIT_MASK ) == 0x0 )
        ret_code |= SD_CARD_BUSY;
    }
  }
  
  // Issue SEND_CID command then parse contents of CID register
  if( !ret_code )
  {
    ret_code |= sd_sendreceive_spi( sd_card_global, SEND_CID, SD_NO_ARG );
    sd_parse_cid_register( sd_card_global, (alt_u8*)(sd_card_global->data_buff_base_addr) );
  }
  
  // Issue SEND_CSD command then parse contents of CSD register
  if( !ret_code )
  {
    ret_code |= sd_sendreceive_spi( sd_card_global, SEND_CSD, SD_NO_ARG );
    sd_parse_csd_register( sd_card_global, (alt_u8*)(sd_card_global->data_buff_base_addr) );
  }
 
  // Issue SEND_STATUS command
  if( !ret_code )
    ret_code |= sd_sendreceive_spi( sd_card_global, SEND_STATUS, SD_NO_ARG );
  
  // Issue SET_BLOCKLEN command
  if( !ret_code )
    ret_code |= sd_sendreceive_spi( sd_card_global, SET_BLOCKLEN, (alt_u32)sd_card_global->read_block_length ); 
  
  return( ret_code );

}

/*****************************************************************************
*  Function: sd_fat_mount_all
*
*  Purpose: Mounts all SD Card FAT volumes.
*
*  Returns: Number of volumes mounted.
*
*****************************************************************************/
int sd_fat_mount_all( void )
{  
  int volumes_mounted = 0;

  volumes_mounted = rb_fat_disk_mount_all();

  return (volumes_mounted);
}

/*****************************************************************************
*  Function: sd_open
*
*  Purpose: SD Card-specific wrapper for FAT function open().
*
*****************************************************************************/
int sd_open( const char* pathname, int flags )
{
    return( rb_fat_open( pathname, flags ));
}

/*****************************************************************************
*  Function: sd_close
*
*  Purpose: SD Card-specific wrapper for FAT function close().
*
*****************************************************************************/
int sd_close(int fd)
{
    return( rb_fat_close( fd ));
}

/*****************************************************************************
*  Function: sd_read
*
*  Purpose: SD Card-specific wrapper for FAT function read().
*
*****************************************************************************/
ssize_t sd_read(int fd, void* buf, size_t count)
{
    return( rb_fat_read( fd, buf, count));
}

/*****************************************************************************
*  Function: sd_write
*
*  Purpose: SD Card-specific wrapper for FAT function write().
*
*****************************************************************************/
ssize_t sd_write(int fd, const void* buf, size_t count)
{
    return( rb_fat_write( fd, buf, count));
}

/*****************************************************************************
*  Function: sd_list
*
*  Purpose: Wrapper for FAT code which lists all the files in a directory.
*
*  Returns: Number of files found.
*
*****************************************************************************/
int sd_list( char* pathname, char* buf )
{
    return( rb_fat_list( pathname, buf ));
}

/*****************************************************************************
*  Function: sd_lseek
*
*  Purpose: SD Card-specific wrapper for FAT function lseek().
*
*****************************************************************************/
int sd_lseek(int fd, off_t offset, int whence)
{
    return( rb_fat_lseek( fd, offset, whence ));
}

/*****************************************************************************
*  Function: sd_fstat
*
*  Purpose: SD Card-specific wrapper for FAT function rename().
*
*****************************************************************************/
int sd_fstat( int fd, struct stat *st )
{
    return( rb_fat_fstat( fd, st ));
}

/*****************************************************************************
*  Function: sd_filesize
*
*  Purpose: SD Card-specific wrapper for FAT function filesize().
*
*****************************************************************************/
off_t sd_filesize(int fd)
{
    return( rb_fat_filesize( fd ));
}

/*****************************************************************************
*  Function: sd_remove
*
*  Purpose: SD Card-specific wrapper for FAT function remove().
*
*****************************************************************************/
int sd_remove(const char* name)
{
    return( rb_fat_remove( name ));
}

/*****************************************************************************
*  Function: sd_creat
*
*  Purpose: SD Card-specific wrapper for FAT function creat().
*
*****************************************************************************/
int sd_creat(const char *pathname, mode_t mode)
{
    return( rb_fat_creat( pathname, mode ));
}

/*****************************************************************************
*  Function: sd_rename
*
*  Purpose: SD Card-specific wrapper for FAT function rename().
*
*****************************************************************************/
int sd_rename(const char* path, const char* newpath)
{
    return( rb_fat_rename( path, newpath ));
}

/*****************************************************************************
*  Function: sd_mkdir
*
*  Purpose: SD Card-specific wrapper for FAT function mkdir().
*
*****************************************************************************/
int sd_mkdir(const char *name, int mode)
{
    return( rb_fat_mkdir( name, mode ));
}

/*****************************************************************************
*  Function: sd_rmdir
*
*  Purpose: SD Card-specific wrapper for FAT function rmdir().
*
*****************************************************************************/
int sd_rmdir(const char* name)
{
    return( rb_fat_rmdir( name ));
}

/*****************************************************************************
*  Function: sd_open_wrapper
*
*  Purpose: We use this wrapper as the callback function from the 
*           HAL "open()" system call. Since that API uses file 
*           descriptor pointers instead of integer file descriptors,
*           we need to use the fd pointer to keep track of our 
*           integer file descriptor.  So we hijack the fd->priv 
*           pointer to do so.  We call the FAT function rb_fat_open()
*           to get our integer file descriptor.
*
*  Returns: Integer file descriptor
*
*****************************************************************************/
int sd_open_wrapper( alt_fd* fd, const char* pathname, int flags )
{
    int ret_code;
    
    // Reduce the path to just that found on the SD Card by stripping off the mount point
    pathname += strlen( sd_card_global->mount_point );
    
    ret_code = rb_fat_open( pathname, flags );
  
  // Here is our hijack of the fd->priv pointer to keep track of the
  // file descriptor given to us by rb_fat_open.
  fd->priv = malloc( sizeof( int ));
  *((int*)(fd->priv)) = ret_code;
    
    return( ret_code );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -