📄 sd_controller.c
字号:
/*****************************************************************************
* 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 + -