Reading PHAT Directories

From Nutwiki
Revision as of 17:03, 27 October 2016 by Harald (Talk | contribs) (1 revision imported)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Test Environments

Comments Nut/OS
4.8.0
Nut/OS
4.9.9
Ethernut 3.0 E NO NT
Ethernut 3.1 D NutThreadYield
added
NT OK
Binaries
EIR 1.0 C Set jumper JP1
to DEBUG mode.
OK
Binaries
NT
AT91SAM7X-EK NT NT
AT91SAM9260-EK NT NT
Compiler: ARM-GCC 4.2.2 ; AVR-GCC 4.3.0

Source Code

<source lang="c">

  1. include <dev/board.h>
  2. include <fs/phatfs.h>
  3. include <dirent.h>
  4. include <stdio.h>
  5. include <io.h>
  6. include <fcntl.h>

int main (void) {

   uint32_t baud = 115200;
   int hvol;
   DIR *dir;
   struct dirent *dent;
   int cnt = 0;
   NutRegisterDevice(&DEV_DEBUG, 0, 0);
   freopen(DEV_DEBUG_NAME, "w", stdout);
   _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
   NutRegisterDevice(&devPhat0, 0, 0);
   NutRegisterDevice(&DEV_MMCARD, 0, 0);

   printf("Mounting card...");
   hvol = _open(DEV_MMCARD_NAME ":1/PHAT0", _O_RDWR | _O_BINARY);
   if (hvol == -1) {
       puts("failed");
   } else {
       puts("OK");
       dir = opendir("PHAT0:/");
       if(dir == NULL) {
           puts("Cannot read root directory");
       } else {
           for (;;) {
               dent = readdir(dir);
               if (dent == NULL) {
                   break;
               }
               puts(dent->d_name);
               cnt++;
           }
           closedir(dir);
       }
       _close(hvol);
   }
   printf("%d entries found\n", cnt);
   for(;;);
   return 0;

} </source>

Output

The program will list all entries in the root directory.

Mounting card...OK
test1.txt
test2.txt
2 entries found

Details

All required header files must be included in the source.

<source lang="c">

  1. include <dev/board.h>
  2. include <fs/phatfs.h>
  3. include <dirent.h>

</source>

The first, dev/board.h, defines some platform independent defaults like DEV_MMCARD and DEV_MMCARD_NAME.

fs/phatfs.h contains definitions of the PHAT filesystem, while dirent.h provides prototypes for reading directories.

As usual, we must register all drivers we want to use. For reading MMC cards, the MMC driver as well as the PHAT files system driver are required.

<source lang="c"> NutRegisterDevice(&devPhat0, 0, 0); NutRegisterDevice(&DEV_MMCARD, 0, 0); </source>

To access the card, it must be mounted first.

<source lang="c"> hvol = _open(DEV_MMCARD_NAME ":1/PHAT0", _O_RDWR | _O_BINARY); </source>

<source lang="c"> dir = opendir("PHAT0:/"); </source>

<source lang="c"> dent = readdir(dir); </source>

<source lang="c"> closedir(dir); </source>

Pitfalls

Interrupts not working

The simple demo presented here may not work with all Nut/OS versions and target boards. Mounting the card fails with error 19 (ENODEV).

When Nut/OS enters the main routine, all interrupts are disabled. They will become automatically enabled on the first context switch. On the other hand, the card detection is interrupt driven. As long as interrupts are disabled, no card detection is signaled and the MMC driver assumes, that no card has been inserted in the socket.

For example, when running on Ethernut 3, our demo will use polling drivers only (devDebug and devNplMmc0) and no context switch takes place, which would enable the card detect interrupt. A simple call

<source lang="c"> NutThreadYield(); </source>

will solve this by forcing a context switch. Add this line before mounting the file system with _open(). Note, that you additionally need to include the header file sys/thread.h.

Alternatively you can use

<source lang="c"> sei(); </source>

for the AVR or

<source lang="c"> asm volatile("mrs r12, cpsr\n"

            "bic r12, r12, #0xC0\n"
            "msr cpsr_c, r12");

</source>

for the ARM to enable interrupts.

See also

External Links

dirent.h Posix standard header for directory traversing.