Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fat Filesystem return no_filesystem even when reading the MBR #220

Closed
mhanuel26 opened this issue Sep 13, 2017 · 14 comments
Closed

Fat Filesystem return no_filesystem even when reading the MBR #220

mhanuel26 opened this issue Sep 13, 2017 · 14 comments

Comments

@mhanuel26
Copy link

I have a hard time to make the sd card Mount_Drive function to work.

The sd card is reading Ok since the snippet code to read it's size and MBR does it correctly, i.e. this snippet prints the 2GB size of my sd card.

      STM32.Board.SDCard_Device.Initialize;

      if STM32.Board.SDCard_Device.Card_Present then
         AIP.IO.Put_Line ("SD card is present");

         SD_Card_Info := STM32.Board.SDCard_Device.Get_Card_Information;

         --  Dump general info about the SD-card
         Capacity := SD_Card_Info.Card_Capacity;

         for Unit of Units loop
            if Capacity < 1000 or else Unit = 'T' then
               Put (5, 70, "SDcard size:" & Capacity'Img & " " & Unit & "B");
               exit;
            end if;

            if Capacity mod 1000 >= 500 then
               Capacity := Capacity / 1000 + 1;
            else
               Capacity := Capacity / 1000;
            end if;
         end loop;
    end if;

Then I call

Status := Mount_Drive ("sdcard", STM32.Board.SDCard_Device'Access);

Inside the Mount_Drive, the function read

Status := Read (Device, MBR);

was returning OK but actually the MBR variable was all in 0's, so I did some debugging and determine that inside the function the assignment was not execute correctly, that is the line

MBR := Tmp; so I rewrite the function a little bit

   function Read
     (Controller  : HAL.Block_Drivers.Any_Block_Driver;
      MBR         : access Master_Boot_Record)
      return File_IO.Status_Code
   is
--        Tmp  : aliased Master_Boot_Record;
      Ptr  : constant Master_Boot_Record_Access := MBR.all'Unchecked_Access;
      Data : aliased HAL.UInt8_Array (1 .. 512) with Address => Ptr.all'Address;
--        Data : aliased HAL.UInt8_Array (1 .. 512) with Address => Tmp'Address;
   begin
      --  Let's read the MBR: located in the first block
      if not Controller.Read (0, Data) then
         return File_IO.Disk_Error;
      end if;

--        MBR := Tmp;  --  This was not working at all

      if MBR.Signature /= 16#AA55# then
         return File_IO.No_MBR_Found;
      end if;

      return File_IO.OK;
   end Read;

Notice that I am using an access for MBR, so the calling function change to

Status := Read (Device, MBR'Access);

after that I can read the MBR correctly and it pass the sanity checks

     if Valid (MBR, P)
       and then Get_Type (MBR, P) in 6 | 11 .. 12

but then in function function Mount_Drive, the call to

        Status := Convert (Open (Controller => Device,
                                 LBA        => LBA (MBR, P),
                                 FS         => FAT_FS.all));

is giving me no_filesystem, because inside it when it checks the Window for 55AA,

which it's done in Initialize_FS

  if FS.Window (510 .. 511) /= (16#55#, 16#AA#) then
     Status := No_Filesystem;
     return;
  end if;

it fails since WIndow is all 0's.

I guess the following call done prior to the Open call

FAT_FS := new FAT_Filesystem;

should have read or set that Window "data".

sd_card_mbr_ok

@Fabien-Chouteau
Copy link
Member

Fabien-Chouteau commented Sep 13, 2017

Hi Manuel,

is giving me no_filesystem, because inside it when it checks the Window for 55AA,

which it's done in Initialize_FS

if FS.Window (510 .. 511) /= (16#55#, 16#AA#) then
Status := No_Filesystem;
return;
end if;

it fails since WIndow is all 0's.

The windows data should be loaded from the SDcard before the 55AA check. With this function:
Status := FS.Ensure_Block (0);

It looks like there's a problem with SDcard reads here. Maybe it's an optimization or a cache problem. Which board are you using?

@mhanuel26
Copy link
Author

mhanuel26 commented Sep 13, 2017

Hello Fabien,

I have found that the function you mention

Status := FS.Ensure_Block (0);

is working fine, but I suspect that the block size is not correct,

inside the function Read of stm32_sdmmc.adb the call

  SD_Err := Read_Blocks_DMA
    (This,
     Block_Number * UInt64 (This.Info.Card_Block_Size),
     Data);

when it was failing I found that the Card_Block_Size was set to 1024, I change it manually to 512 during a debug session and it worked, at least to read the disk_parameters, after that it fills up correctly , please see the attached picture

I am still trying to figure out why it was 1024 and not 512.

I am using STM32F769-DISC.

disk_parameters

@mhanuel26
Copy link
Author

I actually found that the block size it's been set to 1024 in the function Compute_Card_Block_Size, not sure if it's ok since the comparison if clause return 2 ** 10, where the 10 comes from the Max_Read_Data_Block_Length, but I am not sure if that is some default value, I am using a 2 GB sd card, the fdisk print partition of the card is

_Command (m for help): p
Disk /dev/sde: 1.9 GiB, 2002780160 bytes, 3911680 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xaf10b81b

Device Boot Start End Sectors Size Id Type
/dev/sde1 * 2048 3911679 3909632 1.9G c W95 FAT32 (LBA)_

compute_card_block_size

@Fabien-Chouteau
Copy link
Member

inside the function Read of stm32_sdmmc.adb the call

SD_Err := Read_Blocks_DMA (This, Block_Number * UInt64 (This.Info.Card_Block_Size), Data);

I think it should always be Block_Number * 512 here. There's a disconnect between SDcard and HAL.Block_Drivers' definition of a block.

@mhanuel26
Copy link
Author

I fix that value to 512 to test and I am getting an exception

In last chance handler
Unhandled Ada Exception: CONSTRAINT_ERROR
Message: file_io.adb:493 range check failed
Call stack traceback locations:

seems the Length value is also disconnected?

exception_set_name

@Fabien-Chouteau
Copy link
Member

I think that's another problem, what is the content and length of Path string?

@mhanuel26
Copy link
Author

Well, It's actually undefined, I did some trace about it, my calling function is

Status := Mount_Drive ("sdcard", STM32.Board.SDCard_Device'Access);

when it first enters there Mount_Point has the "sdcard" value, but after the Read is done it become Unknown, perhaps some memory overlapping, really don't know.

Attached are some self explained screenshots of before and after read is done.

Of course when it enter Mount_Volume it is Unknown as well.

mount_point_before

moun_point_after

@Fabien-Chouteau
Copy link
Member

Maybe revert the changes you made in the Filesystem.MBR.Read function:

 function Read
     (Controller  : HAL.Block_Drivers.Any_Block_Driver;
      MBR         : access Master_Boot_Record)
      return File_IO.Status_Code
   is
--        Tmp  : aliased Master_Boot_Record;
      Ptr  : constant Master_Boot_Record_Access := MBR.all'Unchecked_Access;
      Data : aliased HAL.UInt8_Array (1 .. 512) with Address => Ptr.all'Address;
--        Data : aliased HAL.UInt8_Array (1 .. 512) with Address => Tmp'Address;
   begin
      --  Let's read the MBR: located in the first block
      if not Controller.Read (0, Data) then
         return File_IO.Disk_Error;
      end if;

--        MBR := Tmp;  --  This was not working at all

      if MBR.Signature /= 16#AA55# then
         return File_IO.No_MBR_Found;
      end if;

      return File_IO.OK;
   end Read;

It looks like it's messing with the stack...

@mhanuel26
Copy link
Author

mhanuel26 commented Sep 14, 2017

Hi Fabien,

I did it and now it seems to Mount the Drive correctly, at least it return ok, but now I am trying to print the directory contents as this example code

mount_ok

but it's giving me the following exception

In last chance handler
Unhandled Ada Exception: CONSTRAINT_ERROR
Message: demos.adb:188 discriminant check failed
Call stack traceback locations:

The code at line 188 is

display_current_dir

Am I missing something here on this demo?

Please let me know,

@Fabien-Chouteau
Copy link
Member

Hi @mhanuel26, where is the line 188 here?

@mhanuel26
Copy link
Author

Hi @Fabien-Chouteau,

I didn't notice the line was not clear, the line 188 is

E := Read (Dir);

Have you test the SD card on a STM32F769I board?

@Fabien-Chouteau
Copy link
Member

Hi @mhanuel26,

I don't remember trying specifically on the STM32F769I but I see what the problem is here.

Directory_Entry is a record with a discriminant, here it's Name_Length which is the number of characters in the entry name.

type Directory_Entry (Name_Length : Natural) is record
      Name         : String (1 .. Name_Length);
      Subdirectory : Boolean;
      Read_Only    : Boolean;
      Hidden       : Boolean;
      Symlink      : Boolean;
      Size         : File_Size;
end record;

You can only assign a new value to E if the value of the discriminant is the same. The exception message that you see (Constraint_Error) comes from the fact that you are trying is assign a new value with a different discriminant.

But you don't know that before actually calling the Read() function, so the solution is to declare a new Directory_Entry every time. For instance like this:

loop
   declare
      E : constant Directory_Entry := Read (Dir);
   begin

      exit when E = Invalid_Dir_Entry;

      --  Use the directory entry here

   end;
end loop;

This example, needs to be included in the doc: https://github.com/AdaCore/Ada_Drivers_Library/blob/master/docs/filesystem.md

Can you try with this loop and tell me if that solves your problem?

@mhanuel26
Copy link
Author

Hi @Fabien-Chouteau,

At least the Constraint_Error seems to be fixed but now I am getting NO_MBR_FOUND after Mount_Volume.

I have created the SD card following this guide

https://www.pcworld.com/article/3176712/linux/how-to-format-an-sd-card-in-linux.html

and has some directories and files on it to test. The Sd card is 1GB, here is the openOcd console output

SD card is present
SDcard size: 988 MB
Error when mounting the sdcard:NO_MBR_FOUND

@Fabien-Chouteau
Copy link
Member

This sounds like the problem you described before. What is the content of the fist data block?

BTW, the doc is updated: https://github.com/AdaCore/Ada_Drivers_Library/blob/master/docs/filesystem.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants