diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-11-15 16:44:45 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-11-15 16:44:45 +0000 |
commit | 4bf2eeec797de1c158143d33c572ef38e6ccc015 (patch) | |
tree | 7984e3dd5ddc7d8d474bbbc53f5031863834d50f /nuttx | |
parent | c5c3f5ad84cce90b89cff4d88334789c2bc2e2f9 (diff) | |
download | nuttx-4bf2eeec797de1c158143d33c572ef38e6ccc015.tar.gz nuttx-4bf2eeec797de1c158143d33c572ef38e6ccc015.tar.bz2 nuttx-4bf2eeec797de1c158143d33c572ef38e6ccc015.zip |
Add support for more FAT partitions; support for SD cards greater than 4Gb; TSC2007 touchscreen driver improvements
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4092 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r-- | nuttx/ChangeLog | 8 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/up_svcall.c | 2 | ||||
-rw-r--r-- | nuttx/drivers/input/tsc2007.c | 138 | ||||
-rw-r--r-- | nuttx/drivers/mmcsd/mmcsd_sdio.c | 22 | ||||
-rw-r--r-- | nuttx/fs/fat/fs_fat32.h | 44 | ||||
-rw-r--r-- | nuttx/fs/fat/fs_fat32util.c | 95 |
6 files changed, 245 insertions, 64 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index f0ace7fb4..1873e417b 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -2202,3 +2202,11 @@ PIC32 port is almost complete but still not ready for prime time. 6.12 2011-xx-xx Gregory Nutt <gnutt@nuttx.org> + + * fs/fat/fs_fat32util.c and fs_fat32.h: Logic extended to look in up to + four partitions for a valid FAT file system. + * drivers/input/tsc2007.c: Add support for 8-bit conversions; make sure + that A/D converters are active before requesting conversions. + * drivers/mmcsd0/mmcsd_sdio.c: Increase capacity variable from size_t + to uin64_t (if available) so that SD cards with capacities greater + than 4Gb can be supported. diff --git a/nuttx/arch/arm/src/armv7-m/up_svcall.c b/nuttx/arch/arm/src/armv7-m/up_svcall.c index af00a28c1..248f1fb48 100644 --- a/nuttx/arch/arm/src/armv7-m/up_svcall.c +++ b/nuttx/arch/arm/src/armv7-m/up_svcall.c @@ -202,7 +202,7 @@ static inline void dispatch_syscall(uint32_t *regs) #endif } - /* Set up the return vaue. First, check if a context switch occurred. + /* Set up the return value. First, check if a context switch occurred. * In this case, regs will no longer be the same as current_regs. In * the case of a context switch, we will have to save the return value * in the TCB where it can be returned later when the task is restarted. diff --git a/nuttx/drivers/input/tsc2007.c b/nuttx/drivers/input/tsc2007.c index 718ec1045..910861af6 100644 --- a/nuttx/drivers/input/tsc2007.c +++ b/nuttx/drivers/input/tsc2007.c @@ -91,6 +91,29 @@ #define DEV_FORMAT "/dev/input%d" #define DEV_NAMELEN 16 +/* Commands *****************************************************************/ + +#define TSC2007_SETUP (TSC2007_CMD_FUNC_SETUP) +#ifdef CONFIG_TSC2007_8BIT +# define TSC2007_ACTIVATE_Y (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YON) +# define TSC2007_MEASURE_Y (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YPOS) +# define TSC2007_ACTIVATE_X (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XON) +# define TSC2007_MEASURE_X (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XPOS) +# define TSC2007_ACTIVATE_Z (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YXON) +# define TSC2007_MEASURE_Z1 (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z1POS) +# define TSC2007_MEASURE_Z2 (TSC2007_CMD_8BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z2POS) +# define TSC2007_ENABLE_PENIRQ (TSC2007_CMD_8BIT | TSC2007_CMD_PWRDN_IRQEN) +#else +# define TSC2007_ACTIVATE_Y (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YON) +# define TSC2007_MEASURE_Y (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YPOS) +# define TSC2007_ACTIVATE_X (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XON) +# define TSC2007_MEASURE_X (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XPOS) +# define TSC2007_ACTIVATE_Z (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YXON) +# define TSC2007_MEASURE_Z1 (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z1POS) +# define TSC2007_MEASURE_Z2 (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z2POS) +# define TSC2007_ENABLE_PENIRQ (TSC2007_CMD_12BIT | TSC2007_CMD_PWRDN_IRQEN) +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -156,6 +179,7 @@ static int tsc2007_sample(FAR struct tsc2007_dev_s *priv, FAR struct tsc2007_sample_s *sample); static int tsc2007_waitsample(FAR struct tsc2007_dev_s *priv, FAR struct tsc2007_sample_s *sample); +static int tsc2007_activate(FAR struct tsc2007_dev_s *priv, uint8_t cmd); static int tsc2007_transfer(FAR struct tsc2007_dev_s *priv, uint8_t cmd); static void tsc2007_worker(FAR void *arg); static int tsc2007_interrupt(int irq, FAR void *context); @@ -378,6 +402,48 @@ errout: } /**************************************************************************** + * Name: tsc2007_activate + ****************************************************************************/ + +static int tsc2007_activate(FAR struct tsc2007_dev_s *priv, uint8_t cmd) +{ + struct i2c_msg_s msg; + uint8_t data; + int ret; + + /* Send the setup command (with no ACK) followed by the A/D converter + * activation command (ACKed). + */ + + data = TSC2007_SETUP; + + msg.addr = priv->config->address; /* 7-bit address */ + msg.flags = 0; /* Write transaction, beginning with START */ + msg.buffer = &data; /* Transfer from this address */ + msg.length = 1; /* Send one byte following the address */ + + /* Ignore errors from the setup command (because it is not ACKed) */ + + (void)I2C_TRANSFER(priv->i2c, &msg, 1); + + /* Now activate the A/D converter */ + + data = cmd; + + msg.addr = priv->config->address; /* 7-bit address */ + msg.flags = 0; /* Write transaction, beginning with START */ + msg.buffer = &data; /* Transfer from this address */ + msg.length = 1; /* Send one byte following the address */ + + ret = I2C_TRANSFER(priv->i2c, &msg, 1); + if (ret < 0) + { + idbg("I2C_TRANSFER failed: %d\n", ret); + } + return ret; +} + +/**************************************************************************** * Name: tsc2007_transfer ****************************************************************************/ @@ -529,16 +595,17 @@ static void tsc2007_worker(FAR void *arg) * in the cases previously listed." */ - y = tsc2007_transfer(priv, - (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YPOS)); + (void)tsc2007_activate(priv, TSC2007_ACTIVATE_X); + y = tsc2007_transfer(priv, TSC2007_MEASURE_Y); + /* "Voltage is then applied to the other axis, and the A/D converter * converts the voltage representing the X position on the screen. This * process provides the X and Y coordinates to the associated processor." */ - x = tsc2007_transfer(priv, - (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XPOS)); + (void)tsc2007_activate(priv, TSC2007_ACTIVATE_Y); + x = tsc2007_transfer(priv, TSC2007_MEASURE_X); /* "... To determine pen or finger touch, the pressure of the touch must be * determined. ... There are several different ways of performing this @@ -556,15 +623,14 @@ static void tsc2007_worker(FAR void *arg) * Read Z1 and Z2 values. */ - z1 = tsc2007_transfer(priv, - (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z1POS)); - z2 = tsc2007_transfer(priv, - (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z2POS)); + (void)tsc2007_activate(priv, TSC2007_ACTIVATE_Z); + z1 = tsc2007_transfer(priv, TSC2007_MEASURE_Z1); + (void)tsc2007_activate(priv, TSC2007_ACTIVATE_Z); + z2 = tsc2007_transfer(priv, TSC2007_MEASURE_Z2); /* Power down ADC and enable PENIRQ */ - (void)tsc2007_transfer(priv, - (TSC2007_CMD_12BIT | TSC2007_CMD_PWRDN_IRQEN)); + (void)tsc2007_transfer(priv, TSC2007_ENABLE_PENIRQ); /* Now calculate the pressure using the first method, reduced to: * @@ -574,21 +640,23 @@ static void tsc2007_worker(FAR void *arg) if (z1 == 0) { idbg("Z1 zero\n"); - goto errout; + pressure = 0; } + else + { + pressure = (x * config->rxplate * (z2 - z1)) / z1; + pressure = (pressure + 2048) >> 12; - pressure = (x * config->rxplate * (z2 - z1)) / z1; - pressure = (pressure + 2048) >> 12; - - ivdbg("Position: (%d,%4d) pressure: %u z1/2: (%d,%d)\n", - x, y, pressure, z1, z2); + ivdbg("Position: (%d,%4d) pressure: %u z1/2: (%d,%d)\n", + x, y, pressure, z1, z2); - /* Ignore out of range caculcations */ + /* Ignore out of range caculcations */ - if (pressure > 0x0fff) - { - idbg("Dropped out-of-range pressure: %d\n", pressure); - goto errout; + if (pressure > 0x0fff) + { + idbg("Dropped out-of-range pressure: %d\n", pressure); + pressure = 0; + } } /* Save the measurements */ @@ -878,17 +946,27 @@ static ssize_t tsc2007_read(FAR struct file *filep, FAR char *buffer, size_t len report->point[0].flags = TOUCH_UP | TOUCH_ID_VALID; } - else if (sample.contact == CONTACT_DOWN) + else { - /* First contact */ + if (sample.contact == CONTACT_DOWN) + { + /* First contact */ - report->point[0].flags = TOUCH_DOWN | TOUCH_ID_VALID | TOUCH_POS_VALID | TOUCH_PRESSURE_VALID; - } - else /* if (sample->contact == CONTACT_MOVE) */ - { - /* Movement of the same contact */ + report->point[0].flags = TOUCH_DOWN | TOUCH_ID_VALID | TOUCH_POS_VALID; + } + else /* if (sample->contact == CONTACT_MOVE) */ + { + /* Movement of the same contact */ + + report->point[0].flags = TOUCH_MOVE | TOUCH_ID_VALID | TOUCH_POS_VALID; + } - report->point[0].flags = TOUCH_MOVE | TOUCH_ID_VALID | TOUCH_POS_VALID | TOUCH_PRESSURE_VALID; + /* A pressure measurement of zero means that pressure is not available */ + + if (report->point[0].pressure != 0) + { + report->point[0].flags |= TOUCH_PRESSURE_VALID; + } } ret = SIZEOF_TOUCH_SAMPLE_S(1); @@ -1163,7 +1241,7 @@ int tsc2007_register(FAR struct i2c_dev_s *dev, * waiting for a touch event. */ - ret = tsc2007_transfer(priv, (TSC2007_CMD_12BIT | TSC2007_CMD_PWRDN_IRQEN)); + ret = tsc2007_transfer(priv, TSC2007_ENABLE_PENIRQ); if (ret < 0) { idbg("tsc2007_transfer failed: %d\n", ret); diff --git a/nuttx/drivers/mmcsd/mmcsd_sdio.c b/nuttx/drivers/mmcsd/mmcsd_sdio.c index 6fcae1960..b30610ca5 100644 --- a/nuttx/drivers/mmcsd/mmcsd_sdio.c +++ b/nuttx/drivers/mmcsd/mmcsd_sdio.c @@ -38,6 +38,7 @@ ****************************************************************************/ #include <nuttx/config.h> +#include <nuttx/compiler.h> #include <sys/types.h> #include <sys/ioctl.h> @@ -128,11 +129,15 @@ struct mmcsd_state_s /* Memory card geometry (extracted from the CSD) */ - uint8_t blockshift; /* Log2 of blocksize */ + uint8_t blockshift; /* Log2 of blocksize */ uint16_t blocksize; /* Read block length (== block size) */ - size_t nblocks; /* Number of blocks */ - size_t capacity; /* Total capacity of volume */ + uint32_t nblocks; /* Number of blocks */ +#ifdef CONFIG_HAVE_LONG_LONG + uint64_t capacity; /* Total capacity of volume */ +#else + uint32_t capacity; /* Total capacity of volume (Limited to 4Gb) */ +#endif /* Read-ahead and write buffering support */ #if defined(CONFIG_FS_WRITEBUFFER) || defined(CONFIG_FS_READAHEAD) @@ -635,7 +640,11 @@ static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, uint32_t csd[4]) */ uint32_t csize = ((csd[1] & 0x3f) << 16) | (csd[2] >> 16); +#ifdef CONFIG_HAVE_LONG_LONG + priv->capacity = ((uint64_t)(csize + 1)) << 19; +#else priv->capacity = (csize + 1) << 19; +#endif priv->blockshift = 9; priv->blocksize = 1 << 9; priv->nblocks = priv->capacity >> 9; @@ -802,8 +811,9 @@ static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, uint32_t csd[4]) fvdbg(" FILE_FORMAT: %d ECC: %d (MMC) CRC: %d\n", decoded.fileformat, decoded.mmcecc, decoded.crc); - fvdbg("Capacity: %dKb, Block size: %db, nblocks: %d wrprotect: %d\n", - priv->capacity / 1024, priv->blocksize, priv->nblocks, priv->wrprotect); + fvdbg("Capacity: %luKb, Block size: %db, nblocks: %d wrprotect: %d\n", + (unsigned long)(priv->capacity / 1024), priv->blocksize, + priv->nblocks, priv->wrprotect); #endif } @@ -2759,7 +2769,7 @@ static int mmcsd_probe(FAR struct mmcsd_state_s *priv) { /* Yes... */ - fvdbg("Capacity: %d Kbytes\n", priv->capacity / 1024); + fvdbg("Capacity: %lu Kbytes\n", (unsigned long)(priv->capacity / 1024)); priv->mediachanged = true; /* Set up to receive asynchronous, media removal events */ diff --git a/nuttx/fs/fat/fs_fat32.h b/nuttx/fs/fat/fs_fat32.h index 026d87a6d..536e8fd7e 100644 --- a/nuttx/fs/fat/fs_fat32.h +++ b/nuttx/fs/fat/fs_fat32.h @@ -129,10 +129,12 @@ */ /* 446@0: Generally unused and zero; but may * include IDM Boot Manager menu entry at 8@394 */ +#define PART_ENTRY(n) (446+((n) << 4)) /* n = 0,1,2,3 */ #define PART_ENTRY1 446 /* 16@446: Partition table, first entry */ #define PART_ENTRY2 462 /* 16@462: Partition table, second entry */ - /* 32@478: Unused, should be zero */ -#define PART_SIGNATURE /* 2@510: Valid partitions have 0x55aa here */ +#define PART_ENTRY3 478 /* 16@478: Partition table, third entry */ +#define PART_ENTRY4 494 /* 16@494: Partition table, fourth entry */ +#define PART_SIGNATURE 510 /* 2@510: Valid partitions have 0x55aa here */ /**************************************************************************** * These offsets describes one partition table entry. NOTE that ent entries @@ -148,6 +150,26 @@ #define PART_SIZE 12 /* 4@12: Partition size (in sectors) */ /**************************************************************************** + * Partition table types. + */ + +#define PART_TYPE_NONE 0 /* No partition */ +#define PART_TYPE_FAT12 1 /* FAT12 */ +#define PART_TYPE_FAT16A 4 /* FAT16 (Partition smaller than 32MB) */ +#define PART_TYPE_EXT 5 /* Extended MS-DOS Partition */ +#define PART_TYPE_FAT16B 6 /* FAT16 (Partition larger than 32MB) */ +#define PART_TYPE_FAT32 11 /* FAT32 (Partition up to 2048Gb) */ +#define PART_TYPE_FAT32X 12 /* Same as 11, but uses LBA1 0x13 extensions */ +#define PART_TYPE_FAT16X 14 /* Same as 6, but uses LBA1 0x13 extensions */ +#define PART_TYPE_EXTX 15 /* Same as 5, but uses LBA1 0x13 extensions */ + +/**************************************************************************** + * Each FAT "short" 8.3 file name directory entry is 32-bytes long. + * + * Sizes and limits + */ + +/**************************************************************************** * Each FAT "short" 8.3 file name directory entry is 32-bytes long. * * Sizes and limits @@ -329,8 +351,11 @@ #define MBR_GETBOOTSIG16(p) UBYTE_VAL(p,BS16_BOOTSIG) #define MBR_GETBOOTSIG32(p) UBYTE_VAL(p,BS32_BOOTSIG) +#define PART_GETTYPE(n,p) UBYTE_VAL(p,PART_ENTRY(n)+PART_TYPE) #define PART1_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY1+PART_TYPE) #define PART2_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY2+PART_TYPE) +#define PART3_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY3+PART_TYPE) +#define PART4_GETTYPE(p) UBYTE_VAL(p,PART_ENTRY4+PART_TYPE) #define DIR_GETATTRIBUTES(p) UBYTE_VAL(p,DIR_ATTRIBUTES) #define DIR_GETNTRES(p) UBYTE_VAL(p,DIR_NTRES) @@ -351,8 +376,11 @@ #define MBR_PUTBOOTSIG16(p,v) UBYTE_PUT(p,BS16_BOOTSIG,v) #define MBR_PUTBOOTSIG32(p,v) UBYTE_PUT(p,BS32_BOOTSIG,v) +#define PART_PUTTYPE(n,p,v) UBYTE_PUT(p,PART_ENTRY(n)+PART_TYPE,v) #define PART1_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY1+PART_TYPE,v) #define PART2_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY2+PART_TYPE,v) +#define PART3_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY3+PART_TYPE,v) +#define PART4_PUTTYPE(p,v) UBYTE_PUT(p,PART_ENTRY4+PART_TYPE,v) #define DIR_PUTATTRIBUTES(p,v) UBYTE_PUT(p,DIR_ATTRIBUTES,v) #define DIR_PUTNTRES(p,v) UBYTE_PUT(p,DIR_NTRES,v) @@ -378,10 +406,16 @@ #define MBR_GETVOLID16(p) fat_getuint32(UBYTE_PTR(p,BS16_VOLID)) #define MBR_GETVOLID32(p) fat_getuint32(UBYTE_PTR(p,BS32_VOLID)) +#define PART_GETSTARTSECTOR(n,p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY(n)+PART_STARTSECTOR)) +#define PART_GETSIZE(n,p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY(n)+PART_SIZE)) #define PART1_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY1+PART_STARTSECTOR)) #define PART1_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY1+PART_SIZE)) #define PART2_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY2+PART_STARTSECTOR)) #define PART2_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY2+PART_SIZE)) +#define PART3_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY3+PART_STARTSECTOR)) +#define PART3_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY3+PART_SIZE)) +#define PART4_GETSTARTSECTOR(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY4+PART_STARTSECTOR)) +#define PART4_GETSIZE(p) fat_getuint32(UBYTE_PTR(p,PART_ENTRY4+PART_SIZE)) #define MBR_PUTBYTESPERSEC(p,v) fat_putuint16(UBYTE_PTR(p,BS_BYTESPERSEC),v) #define MBR_PUTROOTENTCNT(p,v) fat_putuint16(UBYTE_PTR(p,BS_ROOTENTCNT),v) @@ -389,10 +423,16 @@ #define MBR_PUTVOLID16(p,v) fat_putuint32(UBYTE_PTR(p,BS16_VOLID),v) #define MBR_PUTVOLID32(p,v) fat_putuint32(UBYTE_PTR(p,BS32_VOLID),v) +#define PART_PUTSTARTSECTOR(n,p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY(n)+PART_STARTSECTOR),v) +#define PART_PUTSIZE(n,p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY(n)+PART_SIZE),v) #define PART1_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY1+PART_STARTSECTOR),v) #define PART1_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY1+PART_SIZE),v) #define PART2_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY2+PART_STARTSECTOR),v) #define PART2_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY2+PART_SIZE),v) +#define PART3_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY3+PART_STARTSECTOR),v) +#define PART3_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY3+PART_SIZE),v) +#define PART4_PUTSTARTSECTOR(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY4+PART_STARTSECTOR),v) +#define PART4_PUTSIZE(p,v) fat_putuint32(UBYTE_PTR(p,PART_ENTRY4+PART_SIZE),v) #ifdef CONFIG_FAT_LFN # define LDIR_PTRWCHAR1_5(p) UBYTE_PTR(p,LDIR_WCHAR1_5) diff --git a/nuttx/fs/fat/fs_fat32util.c b/nuttx/fs/fat/fs_fat32util.c index 5c402b468..12c2394f0 100644 --- a/nuttx/fs/fat/fs_fat32util.c +++ b/nuttx/fs/fat/fs_fat32util.c @@ -138,6 +138,10 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs) if (MBR_GETSIGNATURE(fs->fs_buffer) != BOOT_SIGNATURE16 || MBR_GETBYTESPERSEC(fs->fs_buffer) != fs->fs_hwsectorsize) { + fdbg("ERROR: Signature: %04x FS sectorsize: %d HW sectorsize: %d\n", + MBR_GETSIGNATURE(fs->fs_buffer), MBR_GETBYTESPERSEC(fs->fs_buffer), + fs->fs_hwsectorsize); + return -ENODEV; } @@ -172,6 +176,9 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs) if (!fs->fs_nfatsects || fs->fs_nfatsects >= fs->fs_hwnsectors) { + fdbg("ERROR: fs_nfatsects %d fs_hwnsectors: %d\n", + fs->fs_nfatsects, fs->fs_hwnsectors); + return -ENODEV; } @@ -189,6 +196,9 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs) if (!fs->fs_fattotsec || fs->fs_fattotsec > fs->fs_hwnsectors) { + fdbg("ERROR: fs_fattotsec %d fs_hwnsectors: %d\n", + fs->fs_fattotsec, fs->fs_hwnsectors); + return -ENODEV; } @@ -197,6 +207,9 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs) fs->fs_fatresvdseccount = MBR_GETRESVDSECCOUNT(fs->fs_buffer); if (fs->fs_fatresvdseccount > fs->fs_hwnsectors) { + fdbg("ERROR: fs_fatresvdseccount %d fs_hwnsectors: %d\n", + fs->fs_fatresvdseccount, fs->fs_hwnsectors); + return -ENODEV; } @@ -210,6 +223,9 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs) ndatasectors = fs->fs_fattotsec - fs->fs_fatresvdseccount - ntotalfatsects - rootdirsectors; if (ndatasectors > fs->fs_hwnsectors) { + fdbg("ERROR: ndatasectors %d fs_hwnsectors: %d\n", + ndatasectors, fs->fs_hwnsectors); + return -ENODEV; } @@ -235,11 +251,14 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs) } else if (!notfat32) { - fs->fs_fsinfo = fs->fs_fatbase + MBR_GETFSINFO(fs->fs_buffer); - fs->fs_type = FSTYPE_FAT32; + fs->fs_fsinfo = fs->fs_fatbase + MBR_GETFSINFO(fs->fs_buffer); + fs->fs_type = FSTYPE_FAT32; } else { + fdbg("ERROR: notfat32: %d fs_nclusters: %d\n", + notfat32, fs->fs_nclusters); + return -ENODEV; } @@ -550,37 +569,63 @@ int fat_mount(struct fat_mountpt_s *fs, bool writeable) /* The contents of sector 0 is not a boot record. It could be a * partition, however. Assume it is a partition and get the offset * into the partition table. This table is at offset MBR_TABLE and is - * indexed by 16x the partition number. Here we support only - * partition 0. - * - * Check if the partition exists and, if so, get the bootsector for that - * partition and see if we can find the boot record there. + * indexed by 16x the partition number. */ + + int i; + for (i = 0; i < 4; i++) + { + /* Check if the partition exists and, if so, get the bootsector for that + * partition and see if we can find the boot record there. + */ - if (PART1_GETTYPE(fs->fs_buffer) == 0) - { - fdbg("No MBR or partition\n"); - goto errout_with_buffer; - } + uint8_t part = PART_GETTYPE(i, fs->fs_buffer); + fvdbg("Partition %d, offset %d, type %d\n", i, PART_ENTRY(i), part); - /* There appears to be a partition, get the sector number of the - * partition (LBA) - */ + if (part == 0) + { + fvdbg("No partition %d\n", i); + continue; + } - fs->fs_fatbase = PART1_GETSTARTSECTOR(fs->fs_buffer); + /* There appears to be a partition, get the sector number of the + * partition (LBA) + */ - /* Read the new candidate boot sector */ + fs->fs_fatbase = PART_GETSTARTSECTOR(i, fs->fs_buffer); - ret = fat_hwread(fs, fs->fs_buffer, fs->fs_fatbase, 1); - if (ret < 0) - { - goto errout_with_buffer; - } + /* Read the new candidate boot sector */ - /* Check if this is a boot record */ + ret = fat_hwread(fs, fs->fs_buffer, fs->fs_fatbase, 1); + if (ret < 0) + { + /* Failed to read the sector */ - ret = fat_checkbootrecord(fs); - if (ret != OK) + goto errout_with_buffer; + } + + /* Check if this is a boot record */ + + ret = fat_checkbootrecord(fs); + if (ret == OK) + { + /* Break out of the loop if a valid boot record is found */ + + fvdbg("MBR found in partition %d\n", i); + break; + } + + /* Re-read sector 0 so that we can check the next partition */ + + fvdbg("Partition %d is not an MBR\n", i); + ret = fat_hwread(fs, fs->fs_buffer, 0, 1); + if (ret < 0) + { + goto errout_with_buffer; + } + } + + if (i > 3) { fdbg("No valid MBR\n"); goto errout_with_buffer; |