Failing pf_mount using PetitFS, cannot determine why?

Go To Last Post
32 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Afternoon all,

 

After several days of debugging, I thought I'd resort to a forum post on a topic that has clearly been discussed lots in the past - but I've not been able to search out a thread that answers quite my question.

 

I'm adding SD card functionality to a project I've been working on for some time using chan's PetitFS, but have come across a sticking point! In summary, I cannot mount the card.

 

I've got an initialisation function which initialises the SD card, mounts and opens. I can successfully initialise the SD card, when when moving onto mounting the card, pf_mount returns FR_DISK_ERR. My init function is as per below, I've debugged through this using JTAG and can see a good return from sd_io_init, which is correctly detecting the card as SDHC. The card is a 16GB SDHC card, formatted to FAT32, and pffconf.h has FAT32 enabled only, not FAT/FAT16. I also added in some simple LED debugging below where two (only have 2 spare debug LEDs on my board) LEDs turn on, and get switched off if an error is returned. After calling pf_mount, I used a second if statement to confirm FR_DISK_ERR was the returned fault that I was seeing through JTAG, which it is.

 

void sd_init(void){
	DSTATUS status;
	FRESULT result;
	
	PORTD |= (1 << L1) | (1 << L2);

	/* Initialize physical drive */
	status = sd_io_init();
	if (status != 0){
		PORTD &= ~(1 << L2);
	}

	/* Mount volume */
	result = pf_mount(&file_system);
	if (result != FR_OK){
		if(result == FR_DISK_ERR){
			PORTD &= ~(1 << L1);
		}
	}

	/* Open file */
	result = pf_open("DATA.DAT");
	if (result != FR_NO_FILE){
		
	}
}

Chan's documentation says FR_DISK_ERROR is a result of a failure in the read_p function, which is called within pf_mount. I've not changed chan's code, all I've done is replace his SPI functions with my own, as the application is already using SPI for many other things.

I've confirmed the hardware is good, by building an example using the latest Arduino SD lib examples, and can successfully init, mount and write to the card. However, it is custom board and I have no desire to use Arduino libraries/IDE - I just thought of it as a simple way to test the hardware. Toolchain, avr-gcc, using AS7. MCU is 1284P.

 

Currently a little lost, and hoping there's a simple gotcha that I've missed, please let me know if there's any additional code you need to see, but I didn't see the value in re-posting library code.

 

Hoping someone can point at where I'm missing the point!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you have JTAG? Id'd breakpoint on all the fail return points in disk_initialize() and find which one it's going through then trace the reason why.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes I do, so my sd_io_init function (which is Chan's disk_initialise) successfully communicates with the card and returns the correct card type from the line:

 

type = (sd_ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */

 

There's a few conditions in pf_mount that can return FR_DISK_ERR, will jump through these now and post back.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, the 2nd to last line in the snippet below from pf_mount, is what is returning FR_DISK_ERR.

 

Seems the card is formatted to 3? 1 is 'Not a FAT boot record', any other value is 'No valid FAT partition is found'. I've formatted the card both with Windows native format tool, and SD Card Formatter.

FRESULT pf_mount (
	FATFS *fs		/* Pointer to new file system object */
)
{
	BYTE fmt, buf[36];
	DWORD bsect, fsize, tsect, mclst;


	FatFs = 0;

	if (sd_io_init() & STA_NOINIT) {	/* Check if the drive is ready or not */
		return FR_NOT_READY;
	}

	/* Search FAT partition on the drive */
	bsect = 0;
	fmt = check_fs(buf, bsect);			/* Check sector 0 as an SFD format */
	if (fmt == 1) {						/* Not an FAT boot record, it may be FDISK format */
		/* Check a partition listed in top of the partition table */
		if (sd_readp(buf, bsect, MBR_Table, 16)) {	/* 1st partition entry */
			fmt = 3;
		} else {
			if (buf[4]) {					/* Is the partition existing? */
				bsect = ld_dword(&buf[8]);	/* Partition offset in LBA */
				fmt = check_fs(buf, bsect);	/* Check the partition */
			}
		}
	}
	if (fmt == 3) return FR_DISK_ERR;
        if (fmt) return FR_NO_FILESYSTEM;    /* No valid FAT patition is found */

 

So the function returning 3 is as below, so the boot record is returning 3. Time to do some reading there... any suggestions on particular material to review?

 

static BYTE check_fs (	/* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
	BYTE *buf,	/* Working buffer */
	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
)
{
	if (sd_readp(buf, sect, 510, 2)) {	/* Read the boot record */
		return 3;
	}
	if (ld_word(buf) != 0xAA55) {			/* Check record signature */
		return 2;
	}

	if (!_FS_32ONLY && !sd_readp(buf, sect, BS_FilSysType, 2) && ld_word(buf) == 0x4146) {	/* Check FAT12/16 */
		return 0;
	}
	if (PF_FS_FAT32 && !sd_readp(buf, sect, BS_FilSysType32, 2) && ld_word(buf) == 0x4146) {	/* Check FAT32 */
		return 0;
	}
	return 1;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jtw_11 wrote:
.. any suggestions on particular material to review?
Three things:

 

1) fatgen103

2) Wikipedia page about MBR

3) Wikipedia page about boot/BPB

 

But if you can just start by posting the first sector of the card contents and I'll decode it anyway.

 

If you have the free (read-only) version of WinHex from X-ways then it can decode MBRs and BPBs for you anyway (it has templates to decode either).

 

These days I also use "Hex Workshop" and I *think* it has MBR/BPB templates too.

 

Bottom line though: unless current card contents matter just get Windows (or whatever you use) for reformat it (not just a wipe, but a full format) in FAT32 format.

 

EDIT:

1) http://download.microsoft.com/do...

2)  https://en.wikipedia.org/wiki/Master_boot_record

3)  https://en.wikipedia.org/wiki/BIOS_parameter_block

 

Oh and between (2) and (3):  https://en.wikipedia.org/wiki/Volume_boot_record

Last Edited: Thu. Mar 19, 2020 - 02:01 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Cliff,

 

So I've imaged the card in WinHex (just had to download the free version).

 

I've now got a large array of data, offset down column 0, 0-9,A-F columns with data. Is sector 0 offset 00000000 or 00000010? Not totally sure what I need to share here!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

Well just sending a copy of the .bin would be good. But the Edit-Copy All menu has some kind "editor display" which could work. Best would actually be this:

 

 

Highlight just the data of the first 512 bytes (0..200 in hex) then do that Copy Block-Into New File operation (assuming the free version enables this?) and call sector0.bin and paste it here as an attachment.

 

But just a simple screen shot of the first sector display would be a start. Basically I want to know if the first sector is an MBR or a BPB

 

Last Edited: Thu. Mar 19, 2020 - 03:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, hang on... Got it, here is sector 0 with 512 bytes of data in... dawned on me when I re-read my last statement, that a sector is 512 byte, thus this is it. Note I've just formatted the card fully, rather than a quick format.

 

Offset       0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

000000000   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000010   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000020   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000030   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000040   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000050   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000060   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000070   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000080   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000090   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
0000000A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
0000000B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
0000000C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
0000000D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
0000000E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
0000000F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000100   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000110   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000120   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000130   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000140   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000150   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000160   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000170   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000180   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000000190   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
0000001A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
0000001B0   00 00 00 00 00 00 00 00  9B 68 55 BD 00 00 00 82           ›hU½   ‚
0000001C0   03 00 0C FE FF FF 00 20  00 00 00 60 CF 01 00 00      þÿÿ     `Ï
0000001D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
0000001E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
0000001F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 00                 U 

 

Post full format, I'm still getting the same errors returned from the pf_mount and associated functions

 

EDIT - Just posted at the same time as you by the looks of things, but contents of sector 0 here we are.

Last Edited: Thu. Mar 19, 2020 - 03:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK so the above is an MBR which means only 1BE..1CD are relevant. In fact within that the only real thing of relevance is the LBA of the first sector in the partition. That is at 1BE + 8 which is 1C6 so it looks like 00 00 20 00 (little endian) so that is the 8,192nd sector to be read next - so that is at byte offset 0x400000 on the media. So read those 512 bytes next and I predict the word "FAT" will be seen in it (probably "FAT32" in fact)

 

PS it's a 16GB card clearly so it will be "FAT32"

Last Edited: Thu. Mar 19, 2020 - 04:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmm.... hands up on this one I'm afraid.

 

Having pasted my file onto the card, looking at the card in WinHex, the offset numbers appear to have changed. I still can see 0, but then 16, 32, 48, 64, 80, 96, 112...

 

The summary window on the right on WinHex does show under 'Alloc. of visible drive space' a Physical sector number of 8192 as you say. I'm either totally lost, or being so new to WinHex am pressing all the wrong buttons.

 

I think my main question here, is what am I needing to ask/look for? I don't see I should be needing to re-write pf_mount, or should I?

 

EDIT - In fact, I think I've got a few questions - the next popping into my mind, is why do I have a MBR at Sector 0 instead of a BPB? Reading through fatgen103 at the moment, MBR doesn't even appear as part of the FAT32 specification?

 

EDIT 2 - Now even more confused. I perhaps see why sector 0 changed drastically with the addition of a file, however I've just formatted (full, not quick) the card again, but had not copied a file to it yet, and it would appear now that I had a BPB, not MBR. Why would this have changed from earlier's format?

 

Offset      0  1  2  3  4  5  6  7   8  9 10 11 12 13 14 15

00000000   EB 58 90 4D 53 44 4F 53  35 2E 30 00 02 40 0A 03   ëX MSDOS5.0  @  
00000016   02 00 00 00 00 F8 00 00  3F 00 FF 00 00 20 00 00        ø  ? ÿ     
00000032   00 60 CF 01 7B 0E 00 00  00 00 00 00 02 00 00 00    `Ï {           
00000048   01 00 06 00 00 00 00 00  00 00 00 00 00 00 00 00                   
00000064   80 00 29 45 A7 B7 C8 4E  4F 20 4E 41 4D 45 20 20   € )E§·ÈNO NAME  
00000080   20 20 46 41 54 33 32 20  20 20 33 C9 8E D1 BC F4     FAT32   3ɎѼô
00000096   7B 8E C1 8E D9 BD 00 7C  88 56 40 88 4E 02 8A 56   {ŽÁŽÙ½ |ˆV@ˆN ŠV
00000112   40 B4 41 BB AA 55 CD 13  72 10 81 FB 55 AA 75 0A   @´A»ªUÍ r  ûUªu 
00000128   F6 C1 01 74 05 FE 46 02  EB 2D 8A 56 40 B4 08 CD   öÁ t þF ë-ŠV@´ Í
00000144   13 73 05 B9 FF FF 8A F1  66 0F B6 C6 40 66 0F B6    s ¹ÿÿŠñf ¶Æ@f ¶
00000160   D1 80 E2 3F F7 E2 86 CD  C0 ED 06 41 66 0F B7 C9   Ñ€â?÷â†ÍÀí Af ·É
00000176   66 F7 E1 66 89 46 F8 83  7E 16 00 75 39 83 7E 2A   f÷áf‰Føƒ~  u9ƒ~*
00000192   00 77 33 66 8B 46 1C 66  83 C0 0C BB 00 80 B9 01    w3f‹F fƒÀ » €¹ 
00000208   00 E8 2C 00 E9 A8 03 A1  F8 7D 80 C4 7C 8B F0 AC    è, é¨ ¡ø}€Ä|‹ð¬
00000224   84 C0 74 17 3C FF 74 09  B4 0E BB 07 00 CD 10 EB   „Àt <ÿt ´ »  Í ë
00000240   EE A1 FA 7D EB E4 A1 7D  80 EB DF 98 CD 16 CD 19   î¡ú}ëä¡}€ëß˜Í Í 
00000256   66 60 80 7E 02 00 0F 84  20 00 66 6A 00 66 50 06   f`€~   „  fj fP 
00000272   53 66 68 10 00 01 00 B4  42 8A 56 40 8B F4 CD 13   Sfh    ´BŠV@‹ôÍ 
00000288   66 58 66 58 66 58 66 58  EB 33 66 3B 46 F8 72 03   fXfXfXfXë3f;Før 
00000304   F9 EB 2A 66 33 D2 66 0F  B7 4E 18 66 F7 F1 FE C2   ùë*f3Òf ·N f÷ñþÂ
00000320   8A CA 66 8B D0 66 C1 EA  10 F7 76 1A 86 D6 8A 56   ŠÊf‹ÐfÁê ÷v †ÖŠV
00000336   40 8A E8 C0 E4 06 0A CC  B8 01 02 CD 13 66 61 0F   @ŠèÀä  Ì¸  Í fa 
00000352   82 74 FF 81 C3 00 02 66  40 49 75 94 C3 42 4F 4F   ‚tÿ à  f@Iu”ÃBOO
00000368   54 4D 47 52 20 20 20 20  00 00 00 00 00 00 00 00   TMGR            
00000384   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00                   
00000400   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00                   
00000416   00 00 00 00 00 00 00 00  00 00 00 00 0D 0A 44 69                 Di
00000432   73 6B 20 65 72 72 6F 72  FF 0D 0A 50 72 65 73 73   sk errorÿ  Press
00000448   20 61 6E 79 20 6B 65 79  20 74 6F 20 72 65 73 74    any key to rest
00000464   61 72 74 0D 0A 00 00 00  00 00 00 00 00 00 00 00   art             
00000480   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00                   
00000496   00 00 00 00 00 00 00 00  AC 01 B9 01 00 00 55 AA           ¬ ¹   Uª

 

Last Edited: Thu. Mar 19, 2020 - 06:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The whole point of FatFs's mount is that cards can have either an MBR or a BPB in sector 0. If there's an MBR the it's generally assumed that of the 4 partition entries only the first will be used and it will point to the offset where the BPB will be found. So the two options are MBR then BPB or just BPB. An MBR opens the potential for multiple partitions but in reality on SD of it exists there will be only a single partition.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks again Cliff, in my last post however - is that not a BPB in Sector 0 now after reformatting in full?

Regardless of BPB or MBR, pf_mount() still returns FR_DISK_ERR.

I get the impression you're trying to help me by making me help myself (which to be clear, that works for me) but I'm afraid I'm missing the hint entirely at the moment unfortunately!

It seems I've got a good BPB, can communicate with the card, but still cannot mount using the standard PetitFS code, I just have missed something along the way here!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The card is a 16GB SDHC card

Are you sure that the version of the code can support this? I haven't used the code for many years but I seem to remember that some large cards were not supported, maybe it has changed now??

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's a good question, I've had a dig through the documentation I've got but I can't find anything about capacity.

Unfortunately Chan's site is down at the moment however!

Edit - I should note, I've got a 2GB SD1 card also, but oddly it causes some sort of bus contention issue and the other SPI devices on the bus no longer reply with the card inserted.

Last Edited: Thu. Mar 19, 2020 - 10:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jtw_11 wrote:
but I'm afraid I'm missing the hint entirely at the moment unfortunately!
I am just suggesting you dig deeper into why in #4 it is getting a 3 result. That is this:

		if (sd_readp(buf, bsect, MBR_Table, 16)) {	/* 1st partition entry */
			fmt = 3;

then this:

	if (fmt == 3) return FR_DISK_ERR;

The implication here is that this sd_readp() did not return 0 (which I guess is FR_OK) so fmt was set to 3 and that's why this return DISK_ERR. So the job here is then to determine WHY did sd_readp() not return 0 and is ts something to do with "bad information" in the MBR or BPB.

Actually when I look at:

	bsect = 0;
	fmt = check_fs(buf, bsect);			/* Check sector 0 as an SFD format */
	if (fmt == 1) {						/* Not an FAT boot record, it may be FDISK format */
		/* Check a partition listed in top of the partition table */
		if (sd_readp(buf, bsect, MBR_Table, 16)) {	/* 1st partition entry */

as "bsect" is passed by value not reference to check_fs() nothing here can be changing it so I guess this *is* reading sector 0? In fact I guess that a read sector 0 must have worked inside check_fs(), otherwise how could it know fmt==1 

 

But, really, this is why I generally debug with a JTAG - with that there'd be no mystery - you could follow it into things like check_fs() see what it reads, see how it determines a return value then follow it into the subsequent sd_readp() and see what goes on inside there - also example what all the buf/bsect/MBR_Table parameters are set to as it goes into the call, etc etc.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, documenting my debug process over JTAG below, as this usually flushes out the answer writing it down.

 

clawson wrote:

 

The implication here is that this sd_readp() did not return 0 (which I guess is FR_OK) so fmt was set to 3 and that's why this return DISK_ERR. So the job here is then to determine WHY did sd_readp() not return 0 and is ts something to do with "bad information" in the MBR or BPB.

Actually when I look at:

	bsect = 0;
	fmt = check_fs(buf, bsect);			/* Check sector 0 as an SFD format */
	if (fmt == 1) {						/* Not an FAT boot record, it may be FDISK format */
		/* Check a partition listed in top of the partition table */
		if (sd_readp(buf, bsect, MBR_Table, 16)) {	/* 1st partition entry */

as "bsect" is passed by value not reference to check_fs() nothing here can be changing it so I guess this *is* reading sector 0? In fact I guess that a read sector 0 must have worked inside check_fs(), otherwise how could it know fmt==1 

 

But, really, this is why I generally debug with a JTAG - with that there'd be no mystery - you could follow it into things like check_fs() see what it reads, see how it determines a return value then follow it into the subsequent sd_readp() and see what goes on inside there - also example what all the buf/bsect/MBR_Table parameters are set to as it goes into the call, etc etc.

 

So check_fs() is returning 3, not a 1 thus assigning fmt = 1 straight from the call of check_fs(). Therefore the call to read the 1st partition entry never takes places, and instead I jump straight to 

 

if (fmt == 3) return FR_DISK_ERR;

The 3 is being returned by check_fs(), which is reading at offset 510 from the BPB, which according to fatgen103 should contain 0xAA55. Using Winhex to check sector 0 on the card I can see that address 510 & 511 do contain 55 AA (question here that I'm wondering: do I have a big/little endian problem). Regardless, this doesn't appear to be the issue as 3 is returned prior to the check for 0xAA55, specifically - 3 is being returned from the call to sd_readp().

 

Offset      0  1  2  3  4  5  6  7   8  9 10 11 12 13 14 15

00000496   00 00 00 00 00 00 00 00  AC 01 B9 01 00 00 55 AA           ¬ ¹   Uª

 

/*-----------------------------------------------------------------------*/
/* Check a sector if it is an FAT boot record                            */
/*-----------------------------------------------------------------------*/

static BYTE check_fs (	/* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
	BYTE *buf,	/* Working buffer */
	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
)
{
	if (sd_readp(buf, sect, 510, 2)) {	/* Read the boot record */
		return 3;
	}
	if (ld_word(buf) != 0xAA55) {			/* Check record signature */
		return 2;
	}

	if (!_FS_32ONLY && !sd_readp(buf, sect, BS_FilSysType, 2) && ld_word(buf) == 0x4146) {	/* Check FAT12/16 */
		return 0;
	}
	if (PF_FS_FAT32 && !sd_readp(buf, sect, BS_FilSysType32, 2) && ld_word(buf) == 0x4146) {	/* Check FAT32 */
		return 0;
	}
	return 1;
}

sd_readp() returns a one, which causes the if statement to test true, and execute the return 3 statement. The return of 1 from sd_readp() being RES_ERROR. Chans documentation describes RES_ERROR as 

 

RES_ERROR
Any hard error occured during the read operation and could not recover it.

So digging into sd_readp() in this call... We're passing a pointer to the buffer in check_fs, sector number 0 which is what I'd expect, offset in the sector of 510 (which is what I'd expect having been reading fatgen103), and 2 bytes to read, which is also what I'd expect. So far so good. These values are all confirmed via JTAG debugging.

 

static BYTE check_fs (	/* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
	BYTE *buf,	/* Working buffer */
	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
)
{
	if (sd_readp(buf, sect, 510, 2)) {	/* Read the boot record */
		return 3;
	}

 

So within sd_readp, I'm seeing something odd which I think may just be an artifact of compiler optimisation, when I execute the "if (!(CardType & CT_BLOCK))" statement, it runs through the SPI routines for SD command transfers, and then oddly out to the closing brace of the main scheduler in my app (even though the scheduler is not running at this point). After this has happened, I can no longer read the values of 'sector' passed to sd_readp() as it has been optimised away. I don't know if there is an issue there. I'm assuming it's put been into one of the registers. Register 24 for example is marked in red in the processor status window (which I assume means just been updated) and now has 0xFE as it's value, which is the value of offset within the sector.

 

DRESULT sd_readp (
BYTE *buff,		/* Pointer to the destination object */
DWORD sector,	/* Sector number (LBA) */
UINT offset,	/* Offset in the sector */
UINT count		/* Byte count (bit15:destination) */
){
	DRESULT res;
	BYTE rc;
	UINT bc;

	if (!(CardType & CT_BLOCK))
		sector *= 512;	/* Convert to byte address if needed */

	res = RES_ERROR;
	if (sd_send_command(SD_CMD17, sector) == 0) {	/* READ_SINGLE_BLOCK */

		bc = 40000;	/* Time counter */
		do {				/* Wait for data block */
			rc = spi_transfer(DUMMY_HIGH_BYTE);
		} while (rc == 0xFF && --bc);

		if (rc == 0xFE) {	/* A data block arrived */

			bc = 512 + 2 - offset - count;	/* Number of trailing bytes to skip */

			/* Skip leading bytes in the sector */
			while (offset--)
				spi_transfer(DUMMY_HIGH_BYTE);

			/* Receive a part of the sector */
			if (buff) {	/* Store data to the memory */
				do {
					*buff++ = spi_transfer(DUMMY_HIGH_BYTE);
				} while (--count);
				} else {	/* Forward data to the outgoing stream */
				do {
					// FORWARD(spi_transfer(DUMMY_HIGH_BYTE));
				} while (--count);
			}

			/* Skip trailing bytes in the sector and block CRC */
			do spi_transfer(DUMMY_HIGH_BYTE); while (--bc);

			res = RES_OK;
		}
	}

	spi_select(SD_CARD, DISABLE);
	spi_transfer(DUMMY_HIGH_BYTE);

	return res;
}

So, because of the res = RES_ERROR; statement before the if (sd_send_command(SD_CMD17, sector) == 0) if statement, if this statement does not execute, res remains set to RES_ERROR. Therefore, I thought the issue must be within sd_send_command function, specifically when passing it CMD17. BUT, this if statement executes and does run, so I'm into reading a single block.

 

rc does end up == 0xFE, thus a data block has arrived.

 

I successfully move on to if (buff), which executes but then oddly my breakpoint of res = RES_OK is never hit, and I jump straight to spi_select(SD_CARD, DISABLE);. Again, I think this is compiler optimisation trickery, as when I jump to the closing brace of the function, the res value appears in R28 set to RES_OK. The value of RES_OK == 0, so I should be returning 0, and therefore the statement 'return 3;' in check_fs should not execute because the if test surely has evaluated to 0!?

 

static BYTE check_fs (	/* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
	BYTE *buf,	/* Working buffer */
	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
)
{
	if (sd_readp(buf, sect, 510, 2)) {	/* Read the boot record */
		return 3;
	}
	if (ld_word(buf) != 0xAA55) {			/* Check record signature */
		return 2;
	}

	if (!_FS_32ONLY && !sd_readp(buf, sect, BS_FilSysType, 2) && ld_word(buf) == 0x4146) {	/* Check FAT12/16 */
		return 0;
	}
	if (PF_FS_FAT32 && !sd_readp(buf, sect, BS_FilSysType32, 2) && ld_word(buf) == 0x4146) {	/* Check FAT32 */
		return 0;
	}
	return 1;
}

This is where I am totally suck. sd_readp returns 0, so the if should not execute, yet it is?

 

I've just confirmed this with some simple LED debuggery also added into the end of sd_readp(). The LED does turn off, so res does = RES_OK, but the value the function returns is NOT RES_OK. surprise

 

			res = RES_OK;
		}
	}

	spi_select(SD_CARD, DISABLE);
	spi_transfer(DUMMY_HIGH_BYTE);

	if (res == RES_OK){
		PORTB &= ~(1 << LED_1);
	}

	return res;
}

EDIT - Spelling

Last Edited: Fri. Mar 20, 2020 - 01:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK so I guess this is key:

	if (sd_readp(buf, sect, 510, 2)) {	/* Read the boot record */
		return 3;

as you say it does not return RES_OK (0) so "why not?" Presumably it's because:

	if (sd_send_command(SD_CMD17, sector) == 0) {	/* READ_SINGLE_BLOCK */

does not return 0 ? So what does it return and why? When debugging this kind of thing it's often better to turn:

	if (sd_send_command(SD_CMD17, sector) == 0) {	/* READ_SINGLE_BLOCK */

where the return is just a transitory value in some possibly unknown register into:

    volatile ret_type;
    ret_type = sd_send_command(SD_CMD17, sector);
    if (ret_type == 0) {	/* READ_SINGLE_BLOCK */

then you can break and look at ret_type and be sure what the sd_send_command() actually returned. Presumably it's not 0. If it is not 0 now you start to analyse what happens inside sd_send_command(). What is causing the failure there? and so and so  on ...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Cliff,

 

Indeed, I thought after typing my last long reply to break the if statements out as you say. The result of which is that sd_readp DOES return 0, but seemingly only when I split out the test as you suggest. The sd_send_command function is returning what I expect.

 

static BYTE check_fs (	/* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
	BYTE *buf,	/* Working buffer */
	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
)
{
	volatile uint8_t temp = 8;
	temp = sd_readp(buf, sect, 510, 2);
	if (temp){
		return 3;
	}
	//if (sd_readp(buf, sect, 510, 2)) {	/* Read the boot record */
		//return 3;
	//}

So where I'm failing now is still in check_fs(), but when checking BS_FilSysType32

 

	if (PF_FS_FAT32 && !sd_readp(buf, sect, BS_FilSysType32, 2) && ld_word(buf) == 0x4146) {	/* Check FAT32 */
		return 0;
	}
	return 1;
}

Winhex shows that my card does have the FAT32 string in the BPB. HOWEVER - decimal address 84 (0x54) in the BPB is the characters 'T3', not '32'. Equally, if we read backwards, we read the chars 'FA'. The address #define for BS_FilSysType32 appears to be correct. Does that mean my BPB is wrong, and if so - how on earth does Windows & Panasonic SD tools manage to create an incorrect BPB, I can't believe that...?

 

Offset      0  1  2  3  4  5  6  7   8  9 10 11 12 13 14 15

00000000   EB 58 90 4D 53 44 4F 53  35 2E 30 00 02 40 0A 03   ëX MSDOS5.0  @
00000016   02 00 00 00 00 F8 00 00  3F 00 FF 00 00 20 00 00        ø  ? ÿ
00000032   00 60 CF 01 7B 0E 00 00  00 00 00 00 02 00 00 00    `Ï {
00000048   01 00 06 00 00 00 00 00  00 00 00 00 00 00 00 00
00000064   80 00 29 45 A7 B7 C8 4E  4F 20 4E 41 4D 45 20 20   € )E§·ÈNO NAME
00000080   20 20 46 41 54 33 32 20  20 20 33 C9 8E D1 BC F4     FAT32   3ɎѼô

Though the note in fatgen103 is interesting... Windows does not look for this, but they recommend the use of it due to the fact some drivers look for it (fatfs being case in point I suppose!).

 

EDIT - I set my temp variable randomly to 8, just to be sure when I read 0, that wasn't the initialised value I was reading. I've confirmed it starts at 8, and is set to 0.

 

Last Edited: Fri. Mar 20, 2020 - 02:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To add to the above... in the call to sd_readp within this 

	if (PF_FS_FAT32 && !sd_readp(buf, sect, BS_FilSysType32, 2) && ld_word(buf) == 0x4146) {	/* Check FAT32 */
		return 0;
	}
	return 1;
}

When debugging, even though I don't have a breakpoint set on spi_select(SD_CARD, DISABLE);, the program won't advance beyond that point... all it's doing is a port manipulation, and is exactly the same function used many many times elsewhere. There is a register value in R28 that decrements every time I try to execute it, but when it eventually gets down to 0, it starts again at 0xFF.

 

Just for clarify, all that function does is:

void spi_select(uint8_t device, uint8_t state){

		switch (device){
			case DISPLAY:
				if (state == ENABLE)
					PORTC &= ~(1 << TFT_CS); // enable CS for display
				else if (state == DISABLE)
					PORTC |= (1 << TFT_CS); // disable CS for display
			break;

			case SD_CARD:
				if (state == ENABLE)
					PORTC &= (~1 << SD_CS); // enable CS for SD card
				else if (state == DISABLE)
					PORTC |= (1 << SD_CS); // disable CS for SD card
			break;
		}
}

 

/*-----------------------------------------------------------------------*/
/* Read Partial Sector                                                   */
/*-----------------------------------------------------------------------*/

DRESULT sd_readp (
BYTE *buff,		/* Pointer to the destination object */
DWORD sector,	/* Sector number (LBA) */
UINT offset,	/* Offset in the sector */
UINT count		/* Byte count (bit15:destination) */
){
	DRESULT res;
	BYTE rc;
	UINT bc;

	if (!(CardType & CT_BLOCK))
		sector *= 512;	/* Convert to byte address if needed */

	res = RES_ERROR;
	if (sd_send_command(SD_CMD17, sector) == 0) {	/* READ_SINGLE_BLOCK */

		bc = 40000;	/* Time counter */
		do {				/* Wait for data block */
			rc = spi_transfer(DUMMY_HIGH_BYTE);
		} while (rc == 0xFF && --bc);

		if (rc == 0xFE) {	/* A data block arrived */

			bc = 512 + 2 - offset - count;	/* Number of trailing bytes to skip */

			/* Skip leading bytes in the sector */
			while (offset--)
				spi_transfer(DUMMY_HIGH_BYTE);

			/* Receive a part of the sector */
			if (buff) {	/* Store data to the memory */
				do {
					*buff++ = spi_transfer(DUMMY_HIGH_BYTE);
				} while (--count);
				} else {	/* Forward data to the outgoing stream */
				do {
					// FORWARD(spi_transfer(DUMMY_HIGH_BYTE));
				} while (--count);
			}

			/* Skip trailing bytes in the sector and block CRC */
			do spi_transfer(DUMMY_HIGH_BYTE); while (--bc);

			res = RES_OK;
		}
	}

	spi_select(SD_CARD, DISABLE);
	spi_transfer(DUMMY_HIGH_BYTE);

	//if (res == RES_OK){
		//PORTB &= ~(1 << LED_1);
	//}

	return res;
}

 

EDIT - I've gotten over the hanging whilst debugging with JTAG, I don't fully understand why (again, appears to be compiler optimisation as the next statement arrow jumps around). I disabled one of the many breakpoints in the function and it carries on.

 

However, I've now put some additional test code in as below, the sd_readp() is returning 0 as it should do, however, checking the buffer contents, instead of reading out 0x4146, the value I've read is 0x40BF despite Winhex reading 0x4146 in these bytes of sector 0? This appears to be the crux of the problem.

 

	temp = 9;
	temp = sd_readp(buf, sect, BS_FilSysType32, 2);
	if(ld_word(buf) == 0x4146){
		PORTB &= ~(1 << LED_0);
	}

	if (PF_FS_FAT32 && !sd_readp(buf, sect, BS_FilSysType32, 2) && ld_word(buf) == 0x4146) {	/* Check FAT32 */
		return 0;
	}
	return 1;
}

EDIT - In fact, it now seems buf when in the pf_mount function ALWAYS contains 0x40BF (EDIT, typo...). Or, I'm sure sure if that's the address of buf, when you click in AS7 on a variable, does it display for value for integers, and the address for arrays? I am so very confused now and any help would be greatly appreciated as I seem to have exhausted all options and simply don't know where to go next.

Last Edited: Fri. Mar 20, 2020 - 11:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Chan's site is down at the moment however!

It's up again, current version is R0.03a of 2019.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looks like it's down again now! Odd.

Earlier on, I thought I'd got some sort of big/little endian problem when I thought the 0x40BF was 0x4146 backwards, but then I unconvinced myself... How frustrating.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Works OK here as of 12:00pm Sydney time.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yep, back up here too!

 

So, I've still been working away on this and have got a little bit further. My whole confusion around why the buffer within check_fs() always contained 0x40BF in two of the general purpose registers, was simply me being, not so smart. It doesn't always contain that value - I've realised now this is the pointer address of the buffer, so looking in the memory view whilst debugging at address 0x40BF, I can see the values of 0xAA55 stored in the lower double word of buf.

data 0x40BF  55 aa 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  Uª.........................
data 0x40DA  00 00 00 14 43 40 e9 00 00 00 40 14 43 40 ee 27 0f 40 ff 04 00 00 00 00 00 00 00  ....C@é...@.C@î'.@ÿ........
data 0x40F5  00 00 00 00 00 15 f1 0c e3 01 53 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??  ......ñ.ã.S................

I can see that I'm reading back 0xAA55 out of the card just fine, but when I perform a second read from the card to read back 0x4146, all that comes back from the card is 0? Despite 0x4146 being there, in the right place, confirmed by WinHex. I also confirmed this checking the status of the SPI buffer directly within my spi_transfer function...

 

So within sd_readp(), when trying to read the file system type, looking for 0x4146, I've followed the code into the spi_transfer function (which categorically does work as a function, else all my other functionality wouldn't function), 

			if (buff) {	/* Store data to the memory */
				do {
					*buff++ = spi_transfer(DUMMY_HIGH_BYTE);
				} while (--count);

I cannot see for the life of me why the card is returning 0s, can anybody help?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I must be missing something. What is looking for 0x4146? I fully understand 0xAA55. I can also imagine a FAT system looking for "FAT12", "FAT16" or "FAT32" but 4146 is "AF", Dunno what significance this has?

 

EDIT: actually above I see:

if (PF_FS_FAT32 && !sd_readp(buf, sect, BS_FilSysType32, 2) && ld_word(buf) == 0x4146) {	/* Check FAT32 */

but where has this code come from? When I look at ff.c that comes in FatFs this is how it determines the filing system:

		/* Determine the FAT sub type */
		sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE);	/* RSV + FAT + DIR */
		if (tsect < sysect) return FR_NO_FILESYSTEM;	/* (Invalid volume size) */
		nclst = (tsect - sysect) / fs->csize;			/* Number of clusters */
		if (nclst == 0) return FR_NO_FILESYSTEM;		/* (Invalid volume size) */
		fmt = 0;
		if (nclst <= MAX_FAT32) fmt = FS_FAT32;
		if (nclst <= MAX_FAT16) fmt = FS_FAT16;
		if (nclst <= MAX_FAT12) fmt = FS_FAT12;

If you read fatgen103 then this is the ONLY valid way to determine filing system. It purely is based on the number of clusters. Where:

#define MAX_FAT12	0xFF5			/* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */
#define MAX_FAT16	0xFFF5			/* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */
#define MAX_FAT32	0x0FFFFFF5		/* Max FAT32 clusters (not specified, practical limit) */

so what on earth is this 0x4146 stuff about and where did it come from??

Last Edited: Mon. Mar 23, 2020 - 02:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh my God now I see it:

00000080   20 20 46 41 54 33 32 20  20 20 33 C9 8E D1 BC F4     FAT32   3ɎѼô

So to determine FAT32 you are looking for the letters A and F as in "FA"T. How on earth does that tell you it's FAT32?? Now if you were looking for "32" a few bytes further on I could maybe understand it.

 

Having said that I do the following:

 

https://github.com/wrightflyer/sdbootloader/blob/master/main.c#L156

 

Look around line 175 onwards. I just use the FATgen103 specified way to read BPB_Fatsz16 and if it's found to be 0 the implication is this is FAT32 so I then read BPB_Fatsz32

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Cliff,

 

I think you're asking exactly the same question as I am... This is all from PetitFS as-is, I've not changed it at all. I put it in one of my posts up the top, I really don't understand how looking at byte offset 84 in sector 0 helps, as all that's there is "FA".

 

Exactly as you say, byte offset 85 might make sense, as then at least you'd pick up "32", but as fatgen103 clearly states, one shouldn't rely on this as said string is not guaranteed to be there! That said, I've tried that, and it still doesn't work as readp() just reads 0s from that location too. Oddly.

 

...I was originally using PetitFS due to having limited RAM available when working with large buffers, I've since worked around that and now have much more RAM available... maybe I should ditch PetitFS and move over to FatFS.

 

PetitFS is throwing up all sorts of questions to me, including - if you call some of the functions with too few arguments, the code compiles still without so much of a warning!? To me, that's a hard no-go at all times!?

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh sorry, I thought this was all about FatFs not Petit! I need to go and have a look at the Petit code and see what it's attempting to do.

 

EDIT: OK I see what he's doing but technically this is NOT the right way to distinguish FAT12/16 versus FAT32. So the code uses:

#define BS_FilSysType		54

#define BS_FilSysType32		82

to read 2 bytes at offset 54 or 82. If it find "FA" at 54 then it's a fair bet it is FAT12 or FAT16 and if it finds "FA" at 82 then it's got to be FAT32.

 

Really (as shown in FatFs) there is only really one real test for the FAT type and that is purely by the number of clusters. If num clusters is less than 4086 it is FAT12, if it's anything from there up to 65525 it is FAT16 and beyond that it must be FAT32

 

But I suppose this is a "quick and easy hack" ?

Last Edited: Mon. Mar 23, 2020 - 04:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah!

 

As best as I can summarise it:

 

  • call a wrapper sd_init function
    • call disk_initialize - GOOD (I renamed this to sd_io_init, as I like to keep the first function word the same as the source file that contains it, and my SD source file contains the functions to store data etc)
    • call pf_mount
      • check for 0xAA55 at offset 510 - GOOD
      • oddly check for FA at offset 82, no idea where - NOT GOOD, sd_readp() function writes 0 into the buffer
    • call pf_open - haven't got this far due to above
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, agreed this is not per-standard method of checking. Regardless, whether you use offset 82 or 85 as thus find "FA" or "32", I suppose this is somewhat irrelevant given it's a bit of a hack.

 

With the above accepted, what I really don't understand is why the readp() function, which writes into the buffer exactly what you'd expect when looking for 0xAA55, no longer behaves as you'd expect when trying to read offset 82. It simple writes 0 into the buffer...

 

It's almost like, the second time you use the function it refuses to read properly. That said, let me try and try 0xAA55 twice in a row - hang on!

 

EDIT:

 

So, if I create a local buffer to check_fs, and read again at location 510 I can confirm I do read 0xAA55 again, so the fundamental response from the card is good.

 

static BYTE check_fs (	/* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
	volatile BYTE *buf,	/* Working buffer */
	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
)
{
	volatile uint8_t temp = 8;
	volatile uint8_t tempbuf[10];

	temp = sd_readp(buf, sect, 510, 2);
	if (temp){
		return 3;
	}
	//if (sd_readp(buf, sect, 510, 2)) {	/* Read the boot record */
		//return 3;
	//}
	if (ld_word(buf) != 0xAA55) {			/* Check record signature */
		return 2;
	}

	temp = sd_readp(&tempbuf, sect, 510, 2);

If I now do this again, but instead of reading at address 510 a second time, read from address 82, I still end up with 0x0000 written into the low double word of my temporary buffer.

 

static BYTE check_fs (	/* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
	volatile BYTE *buf,	/* Working buffer */
	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
)
{
	volatile uint8_t temp = 8;
	volatile uint8_t tempbuf[10];

	temp = sd_readp(buf, sect, 510, 2);
	if (temp){
		return 3;
	}
	//if (sd_readp(buf, sect, 510, 2)) {	/* Read the boot record */
		//return 3;
	//}
	if (ld_word(buf) != 0xAA55) {			/* Check record signature */
		return 2;
	}

	temp = sd_readp(&tempbuf, sect, 82, 2);

	if (!_FS_32ONLY && !sd_readp(buf, sect, BS_FilSysType, 2) && ld_word(buf) == 0x4146) {	/* Check FAT12/16 */
		return 0;
	}

EDIT 2 - Equally, if I try to read at offset 82 BEFORE reading from 510, I still end up with 0 written into my tempbuf. There's something about reading from low offsets that it's not happy about at all...

 

static BYTE check_fs (	/* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
	volatile BYTE *buf,	/* Working buffer */
	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
)
{
	volatile uint8_t temp = 8;
	volatile uint8_t tempbuf[10];

	temp = sd_readp(&tempbuf, sect, 82, 2);

	temp = sd_readp(buf, sect, 510, 2);
	if (temp){
		return 3;
	}
	//if (sd_readp(buf, sect, 510, 2)) {	/* Read the boot record */
		//return 3;
	//}
	if (ld_word(buf) != 0xAA55) {			/* Check record signature */
		return 2;
	}

	if (!_FS_32ONLY && !sd_readp(buf, sect, BS_FilSysType, 2) && ld_word(buf) == 0x4146) {	/* Check FAT12/16 */
		return 0;
	}

EDIT 3: So I just tried a read from 504 instead, which according to Winhex should write 0x01AC into the buffer.. this just writes 0x0000 also!

 

EDIT 4: Ok, so tried a read from 511, with 1 byte only, expecting to read 0xAA. This also reads 0! It is almost as if the card is expecting us to read address 510, and if we don't, to not return anything at all. Scratch that, doing this DOES read 0xAA.

 

static BYTE check_fs (	/* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
	volatile BYTE *buf,	/* Working buffer */
	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
)
{
	volatile uint8_t temp = 8;
	volatile uint8_t tempbuf[10] = {0};
	
	temp = sd_readp(&tempbuf, sect, 511, 1);
	
	temp = sd_readp(buf, sect, 510, 2); // should read 0xAA
	if (temp){
		return 3;
	}
	//if (sd_readp(buf, sect, 510, 2)) {	/* Read the boot record */
		//return 3;
	//}
	if (ld_word(buf) != 0xAA55) {			/* Check record signature */
		return 2;
	}

	if (!_FS_32ONLY && !sd_readp(buf, sect, BS_FilSysType, 2) && ld_word(buf) == 0x4146) {	/* Check FAT12/16 */
		return 0;
	}

 

Last Edited: Mon. Mar 23, 2020 - 05:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, even more odd... here is a look into my card in Winhex

Offset       0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

0000001F0   00 00 00 00 00 00 00 00  AC 01 B9 01 00 00 55 AA           ¬ ¹   Uª

If I try and read for example 6 bytes of data, from address 506, I should expect to read 0xAA55000001B9, instead... I read out 0xAA5500000000, the card simply decides to stop sending anything back that isn't the first 2 bytes. Below is tempbuf in memory @ 0x40A8.

 

data 0x40A8  00 00 00 00 55 aa

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's an MBR not a BPB. Both end 0xAA55 but the rest of the sector is entirely different. Maybe one of the many limitations of Petit is that it just assumes LBA 0 is a BPB?

 

PS why Petit anyway? Are you really trying to do FAT32 from a Tiny? Perhaps it's simply telling you to pick the right AVR for the job?

Last Edited: Mon. Mar 23, 2020 - 06:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No not at all, no Tiny in sight here. As per OP this is running on a 1284P, I was simply memory limited at the time when I started to try and get Petit working, but I can move to full FatFs now... which I think I'm going to have to do.

 

I thought we'd determined up there ^ ^ that the below is a BPB, not MBR? (see post #10)

 

Offset      0  1  2  3  4  5  6  7   8  9 10 11 12 13 14 15

00000000   EB 58 90 4D 53 44 4F 53  35 2E 30 00 02 40 0A 03   ëX MSDOS5.0  @
00000016   02 00 00 00 00 F8 00 00  3F 00 FF 00 00 20 00 00        ø  ? ÿ
00000032   00 60 CF 01 7B 0E 00 00  00 00 00 00 02 00 00 00    `Ï {
00000048   01 00 06 00 00 00 00 00  00 00 00 00 00 00 00 00
00000064   80 00 29 45 A7 B7 C8 4E  4F 20 4E 41 4D 45 20 20   € )E§·ÈNO NAME
00000080   20 20 46 41 54 33 32 20  20 20 33 C9 8E D1 BC F4     FAT32   3ɎѼô
00000096   7B 8E C1 8E D9 BD 00 7C  88 56 40 88 4E 02 8A 56   {ŽÁŽÙ½ |ˆV@ˆN ŠV
00000112   40 B4 41 BB AA 55 CD 13  72 10 81 FB 55 AA 75 0A   @´A»ªUÍ r  ûUªu
00000128   F6 C1 01 74 05 FE 46 02  EB 2D 8A 56 40 B4 08 CD   öÁ t þF ë-ŠV@´ Í
00000144   13 73 05 B9 FF FF 8A F1  66 0F B6 C6 40 66 0F B6    s ¹ÿÿŠñf ¶Æ@f ¶
00000160   D1 80 E2 3F F7 E2 86 CD  C0 ED 06 41 66 0F B7 C9   Ñ€â?÷â†ÍÀí Af ·É
00000176   66 F7 E1 66 89 46 F8 83  7E 16 00 75 39 83 7E 2A   f÷áf‰Føƒ~  u9ƒ~*
00000192   00 77 33 66 8B 46 1C 66  83 C0 0C BB 00 80 B9 01    w3f‹F fƒÀ » €¹
00000208   00 E8 2C 00 E9 A8 03 A1  F8 7D 80 C4 7C 8B F0 AC    è, é¨ ¡ø}€Ä|‹ð¬
00000224   84 C0 74 17 3C FF 74 09  B4 0E BB 07 00 CD 10 EB   „Àt <ÿt ´ »  Í ë
00000240   EE A1 FA 7D EB E4 A1 7D  80 EB DF 98 CD 16 CD 19   î¡ú}ëä¡}€ëß˜Í Í
00000256   66 60 80 7E 02 00 0F 84  20 00 66 6A 00 66 50 06   f`€~   „  fj fP
00000272   53 66 68 10 00 01 00 B4  42 8A 56 40 8B F4 CD 13   Sfh    ´BŠV@‹ôÍ
00000288   66 58 66 58 66 58 66 58  EB 33 66 3B 46 F8 72 03   fXfXfXfXë3f;Før
00000304   F9 EB 2A 66 33 D2 66 0F  B7 4E 18 66 F7 F1 FE C2   ùë*f3Òf ·N f÷ñþÂ
00000320   8A CA 66 8B D0 66 C1 EA  10 F7 76 1A 86 D6 8A 56   ŠÊf‹ÐfÁê ÷v †ÖŠV
00000336   40 8A E8 C0 E4 06 0A CC  B8 01 02 CD 13 66 61 0F   @ŠèÀä  Ì¸  Í fa
00000352   82 74 FF 81 C3 00 02 66  40 49 75 94 C3 42 4F 4F   ‚tÿ à  f@Iu”ÃBOO
00000368   54 4D 47 52 20 20 20 20  00 00 00 00 00 00 00 00   TMGR
00000384   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
00000400   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
00000416   00 00 00 00 00 00 00 00  00 00 00 00 0D 0A 44 69                 Di
00000432   73 6B 20 65 72 72 6F 72  FF 0D 0A 50 72 65 73 73   sk errorÿ  Press
00000448   20 61 6E 79 20 6B 65 79  20 74 6F 20 72 65 73 74    any key to rest
00000464   61 72 74 0D 0A 00 00 00  00 00 00 00 00 00 00 00   art
00000480   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
00000496   00 00 00 00 00 00 00 00  AC 01 B9 01 00 00 55 AA           ¬ ¹   Uª

 

Last Edited: Mon. Mar 23, 2020 - 06:38 PM