/* * File : sdcard.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006, 2007, RT-Thread Develop Team * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rt-thread.org/license/LICENSE * * Change Logs: * Date Author Notes * 2007-12-02 Yi.Qiu the first version * 2010-01-01 Bernard Modify for mini2440 * 2010-10-13 Wangmeng Added sep4020 support */ #include "sdcard.h" #include volatile rt_int32_t RCA; #ifdef RT_USING_DFS /* RT-Thread Device Driver Interface */ #include #include /*GLOBAL SD DEVICE PONITER*/ static struct sd_device *ptr_sddev; static rt_uint8_t gsec_buf[SECTOR_SIZE]; #define USE_TIMEOUT /*This file is to power on/off the SEP4020 SDC*/ /** * This function will power on/off the SEP4020 SDC * * @param sd_ctl: 0/power on; 1/power off * @return none * */ static void sd_pwr(int sd_ctl) { if (sd_ctl) { *(RP)GPIO_PORTA_SEL |= 0x0200; *(RP)GPIO_PORTA_DIR &= (~0x0200); *(RP)GPIO_PORTA_DATA |= 0x0200; } else { *(RP)GPIO_PORTA_SEL |= 0x0200; *(RP)GPIO_PORTA_DIR &= (~0x0200); *(RP)GPIO_PORTA_DATA &= (~0x0200); } } /*a nop operation to delay*/ static void delay (U32 j) { U32 i; for (i=0;ibytes_per_sector = 512; geometry->block_size = 0x200000; //if (CardType == SDIO_HIGH_CAPACITY_SD_CARD) // geometry->sector_count = (SDCardInfo.SD_csd.DeviceSize + 1) * 1024; //else geometry->sector_count = 0x200000;//SDCardInfo.CardCapacity/SDCardInfo.CardBlockSize; } return RT_EOK; } /** * This function will set a hook function, which will be invoked when a memory * block is allocated from heap memory. * * @param hook the hook function */ static rt_size_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) { rt_uint32_t retry = 3; rt_uint8_t status; rt_uint32_t index; ///*take the semaphore struct dfs_partition *part = (struct dfs_partition *)dev->user_data; rt_sem_take(part->lock, RT_WAITING_FOREVER); while(retry--) { if (((rt_uint32_t)buffer % 4 != 0) || ((rt_uint32_t)buffer > 0x20080000)) { for(index = 0;index < size;index++) { status = sd_readblock((part->offset + pos) * SECTOR_SIZE,ptr_sddev->sec_buf); if(status != RT_EOK) break; rt_memcpy((rt_uint8_t *)buffer + (index * SECTOR_SIZE),ptr_sddev->sec_buf,SECTOR_SIZE); } } else { for(index = 0;indexlock); if (status == RT_EOK) return size; rt_kprintf("read failed: %d, buffer 0x%08x\n", status, buffer); return 0; } /** * This function will set a hook function, which will be invoked when a memory * block is allocated from heap memory. * * @param hook the hook function */ static rt_size_t rt_sdcard_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) { int i; rt_uint8_t status; struct dfs_partition *part = (struct dfs_partition *)dev->user_data; if ( dev == RT_NULL ) { rt_set_errno(-DFS_STATUS_EINVAL); return 0; } rt_sem_take(part->lock, RT_WAITING_FOREVER); if (((rt_uint32_t)buffer % 4 != 0) || ((rt_uint32_t)buffer > 0x20080000)) { rt_uint32_t index; for(index=0;indexsec_buf, ((rt_uint8_t*)buffer + index * SECTOR_SIZE), SECTOR_SIZE); status = sd_writeblock((part->offset + index + pos)*SECTOR_SIZE,ptr_sddev->sec_buf); } } else { for(i=0;ioffset + i + pos)*SECTOR_SIZE, (rt_uint8_t*)((rt_uint8_t*)buffer + i * SECTOR_SIZE)); if (status != RT_EOK) break; } } rt_sem_release(part->lock); if (status == RT_EOK) return size; rt_kprintf("read failed: %d, buffer 0x%08x\n", status, buffer); return 0; } rt_err_t rt_hw_sdcard_exit() { if(ptr_sddev->device != RT_NULL) rt_free(ptr_sddev->device); if(ptr_sddev->part != RT_NULL) rt_free(ptr_sddev->part); if(ptr_sddev != RT_NULL) rt_free(ptr_sddev); return RT_EOK; } /** * This function will init sd card * * @param void */ rt_err_t rt_hw_sdcard_init() { /*For test*/ rt_err_t err; rt_int32_t i; char dname[4]; char sname[8]; /*Initialize structure*/ ptr_sddev = (struct sd_device*)rt_malloc(sizeof(struct sd_device)); if(ptr_sddev == RT_NULL) { EOUT("Failed to allocate sdcard device structure\n"); return RT_ENOMEM; } /*sdcard intialize*/ err = sd_init(); if(err != RT_EOK) goto FAIL2; /*set sector buffer*/ ptr_sddev->sec_buf = gsec_buf; ptr_sddev->buf_size = SECTOR_SIZE; ptr_sddev->sdc = (struct sd_c*)SD_BASE; //DBOUT("allocate partition sector buffer OK!"); err = sd_readblock(0,ptr_sddev->sec_buf); if(err != RT_EOK) { EOUT("read first block error\n"); goto FAIL2; } /*sdcard driver initialize*/ ptr_sddev->part = (struct dfs_partition*)rt_malloc(4 * sizeof(struct dfs_partition)); if(ptr_sddev->part == RT_NULL) { EOUT("allocate partition failed\n"); err = RT_ENOMEM; goto FAIL2; } /*alloc device buffer*/ ptr_sddev->device = (struct rt_device*)rt_malloc(4 * sizeof(struct rt_device)); if(ptr_sddev->device == RT_NULL) { EOUT("allocate device failed\n"); err = RT_ENOMEM; goto FAIL1; } ptr_sddev->part_num = 0; err = sd_readblock(0,ptr_sddev->sec_buf); if(err != RT_EOK) { EOUT("Read block 0 to initialize ERROR\n"); goto FAIL1; } for(i=0; i<4; i++) { /* get the first partition */ err = dfs_filesystem_get_partition(&(ptr_sddev->part[i]), ptr_sddev->sec_buf, i); if (err == RT_EOK) { rt_snprintf(dname, 4, "sd%d", i); rt_snprintf(sname, 8, "sem_sd%d", i); ptr_sddev->part[i].lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO); /* register sdcard device */ ptr_sddev->device[i].init = rt_sdcard_init; ptr_sddev->device[i].open = rt_sdcard_open; ptr_sddev->device[i].close = rt_sdcard_close; ptr_sddev->device[i].read = rt_sdcard_read; ptr_sddev->device[i].write = rt_sdcard_write; ptr_sddev->device[i].control = rt_sdcard_control; ptr_sddev->device[i].user_data= &ptr_sddev->part[i]; err = rt_device_register(&ptr_sddev->device[i], dname, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); if(err == RT_EOK) ptr_sddev->part_num++; } else { if(i == 0) { /* there is no partition table */ ptr_sddev->part[0].offset = 0; ptr_sddev->part[0].size = 0; ptr_sddev->part[0].lock = rt_sem_create("sem_sd0", 1, RT_IPC_FLAG_FIFO); /* register sdcard device */ ptr_sddev->device[0].init = rt_sdcard_init; ptr_sddev->device[0].open = rt_sdcard_open; ptr_sddev->device[0].close = rt_sdcard_close; ptr_sddev->device[0].read = rt_sdcard_read; ptr_sddev->device[0].write = rt_sdcard_write; ptr_sddev->device[0].control = rt_sdcard_control; ptr_sddev->device[0].user_data= &ptr_sddev->part[0]; err = rt_device_register(&ptr_sddev->device[0], "sd0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); if(err == RT_EOK) ptr_sddev->part_num++; break; } } } if(ptr_sddev->part_num == 0) goto FAIL0; return err; FAIL0: rt_free(ptr_sddev->device); ptr_sddev->device = RT_NULL; FAIL1: rt_free(ptr_sddev->part); ptr_sddev->part = RT_NULL; FAIL2: rt_free(ptr_sddev); ptr_sddev = RT_NULL; return err; } #endif