cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
jzartman
Observer
Observer
1,437 Views
Registered: ‎06-18-2019

XAPP1079 - 2019.1 - SD access on processor 1

Jump to solution

Hello, all--

Disclaimer: this is my first time posting.

I'm trying to use a Zedboard to create a modified version of XAPP1079 (V1.0.1), that will let me write to the SD card using proc1 (the second processor). I have simplified the provided code for my needs and I have the two processors working together. I'm using the xilffs_v4_1 FAT32 library to handle writes to the SD card. I'm able to write to the SD card from proc1 when it's running by itself, but not when both processors are running together after booting from QSPI. However, I am able to write to the SD card using proc0 (the first processor) when both processors are running. I am receiving this error when proc1 attempts to open/create a file for writing: (from "ff.h") FR_NOT_READY, /* (3) The physical drive cannot work */. To reiterate, this error does not occur when I swap the SD card code over to proc0.

I figure that the FSBL it interfering with SD card access from the second processor somehow. I modified the generated FSBL main function (the first time I've done this) by removing the SD boot section around line 450, but my problem persists. The FSBL is being run from proc0.

Here's my source code. The #define SD in each file is mutually exclusive, and I've used it to verify that SD card access is available to proc0 and not proc1, with all other variables left unchanged.

proc0 main:

#include "sleep.h"
#include "xil_io.h"
#include "xil_mmu.h"
#include "xil_printf.h"
#include "xpseudo_asm.h"

//#define SD

#ifdef SD
#include "ff.h"
#endif

#define sev()           __asm__("sev")
#define CPU1STARTADR    0xfffffff0
#define COMM_VAL        (*(volatile unsigned long *)(0xFFFF0000))

int main() {
#ifdef SD
  bool ok = true;
  bool sd_done = false;
  FATFS fatfs;
  FIL file;
  char filename[32] = "test.dat";
  TCHAR* Path = (TCHAR*) "0:/";
  FRESULT fstatus = FR_OK;
#endif

  //rbuff_S_ptr = (rbuff_struct*) CPU0_DDR_BUFFER;

  //Disable cache on OCM
  Xil_SetTlbAttributes(0xFFFF0000, 0x14de2);  // S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0

  COMM_VAL = 0;

  sleep(5);

  xil_printf("CPU0: writing startaddress for cpu1\n\r");
  Xil_Out32(CPU1STARTADR, 0x00200000);
  dmb();  //waits until write has finished

  xil_printf("CPU0: sending the SEV to wake up CPU1\n\r");
  sev();

  sleep(1);

  while (1) {

    COMM_VAL = 1;
    while (COMM_VAL == 1)
      ;
    xil_printf("CPU0: Hello World CPU 0\n\r");

#ifdef SD
    if (!sd_done) {
      xil_printf("CPU0: Preparing SD     ");
      try {
        // SD Card
        fstatus = f_mount(&fatfs, Path, 0);
        if (fstatus != FR_OK) throw 1;

        // Creates a file on the SD card.
        fstatus = f_open(&file, filename, FA_OPEN_APPEND | FA_WRITE);
        if (fstatus != FR_OK) throw 2;

        // Moves file pointer to the start of the file.
        fstatus = f_lseek(&file, 0);
        if (fstatus != FR_OK) throw 3;

        fstatus = f_write(&file, (const void*) filename, sizeof(filename),
          nullptr);

        fstatus = f_sync(&file);
        xil_printf("DONE\r\n");
      } catch (const int& e) {
        ok = false;
        xil_printf("ERROR %d\r\n", e);
        xil_printf("fstatus (hex) %x\r\n", fstatus);
      }
      if (ok) sd_done = true;
    }
#endif
  }

  return 0;
}

proc1 main:

#include "sleep.h"
#include "xil_cache.h"
#include "xil_io.h"
#include "xil_mmu.h"
#include "xil_printf.h"

#define SD

#ifdef SD
#include "ff.h"
#endif

#define COMM_VAL            (*(volatile unsigned long *)(0xFFFF0000))

int main() {
#ifdef SD
  bool ok = true;
  bool sd_done = false;
  FATFS fatfs;
  FIL file;
  char filename[32] = "test.dat";
  TCHAR* Path = (TCHAR*) "0:/";
  FRESULT fstatus = FR_OK;
#endif

  //Disable cache on OCM
  Xil_SetTlbAttributes(0xFFFF0000, 0x14de2);  // S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0

  while (1) {
    while (COMM_VAL == 0) {
    };
    if (ok) xil_printf("CPU1: Hello World CPU 1\r\n");
    else xil_printf("CPU1: INIT FAILED\r\n");

#ifdef SD
    if (!sd_done) {
      xil_printf("CPU1: Preparing SD     ");
      try {
        // SD Card
        fstatus = f_mount(&fatfs, Path, 0);
        if (fstatus != FR_OK) throw 1;

        // Creates a file on the SD card.
        fstatus = f_open(&file, filename, FA_OPEN_APPEND | FA_WRITE);
        if (fstatus != FR_OK) throw 2;

        // Moves file pointer to the start of the file.
        fstatus = f_lseek(&file, 0);
        if (fstatus != FR_OK) throw 3;

        fstatus = f_write(&file, (const void*) filename, sizeof(filename),
          nullptr);

        fstatus = f_sync(&file);
        xil_printf("DONE\r\n");
      } catch (const int& e) {
        ok = false;
        xil_printf("ERROR %d\r\n", e);
        xil_printf("fstatus (hex) %x\r\n", fstatus);
      }
      if (ok) sd_done = true;
    }
#endif
    sleep(2);   //Delay so output can be seen
    COMM_VAL = 0;

  }

  return 0;
}

Terminal output:

CPU0: writing startaddress for cpu1
CPU0: sending the SEV to wake up CPU1
CPU1: Hello World CPU 1
CPU1: Preparing SD     ERROR 2
fstatus (hex) 3
CPU0: Hello World CPU 0
CPU1: INIT FAILED
...
0 Kudos
Reply
1 Solution

Accepted Solutions
jzartman
Observer
Observer
955 Views
Registered: ‎06-18-2019

Alright, bear with me on this because it's been a while since I had this issue. The issue with the SD card not being able to run on the second core of the processor has to do with the L2 cache being shared between the two cores. I dug through the code to see exactly where the USEAMP flag breaks the SD card functionality and I believe it was somewhere in the cache control functions (xil_cache.h or something like that). ANYWAY, the only thing (I think) that you need to change in the code that I originally posted is to add something like this:

  // Disables L2 Cache on APP1 RAM (0x00200000 - 0x00500000)
  Xil_SetTlbAttributes(0x00200000, 0x14de6);
  Xil_SetTlbAttributes(0x00300000, 0x14de6);
  Xil_SetTlbAttributes(0x00400000, 0x14de6);

I have notes that I took on the different attributes but I'd have to dig a little to find the actual Xilinx documents that I referenced. Each call of Xil_SetTlbAttributes applies to a 1 MB block of memory starting from the address specified by the first argument. This needs to be applied to the DDR addresses used by the second core of the processor. The addresses need to match whatever is in the linker script of the second processor core.

xil_mmu.h also does not need to be included.

View solution in original post

Tags (1)
11 Replies
jzartman
Observer
Observer
1,255 Views
Registered: ‎06-18-2019

The USE_AMP compiler flag on the second processor seems to be the culprit. I created new BSPs for my applications when I was trying out newer versions of the BSP driver software available on Xilinx'x GitHub ( https://github.com/Xilinx/embeddedsw ), but I forgot to add this compiler flag back. I thought that I had solved the problem with the new drivers, but I wanted to identify what driver was specifically creating the issue. Eventually I returned all the BSP drivers to the default 2019.1 state, but things still seemed to be working; I was very confused. After a lot of wasted time, I finally discovered the issue with this compile flag.

I have previously stepped through the SD initialization process to see where things were messing up, and I seem to remember there being some kind of interrupt-related issue. From my understanding, the USE_AMP flag in the second processor's BSP is to prevent the GIC from being re-initialized since the two processors share this resource. It appears that SD card operations require the GIC somehow. Right now, SD access is only working on the second processor without USE_AMP , but I'm trying to do things the "right way", and I assume that the use of this flag is still necessary. Is there an extra step I'm missing to allow SD access? I'm not aware of any SD-specific interrupts, which is another reason I'm puzzled by the idea that the GIC has anything to do with SD card access...

0 Kudos
Reply
a.oerder1
Visitor
Visitor
1,052 Views
Registered: ‎01-17-2020

Hello, I'm running into exactly the same issue as you do.

Searching through the BSP-Sources I could only find references to the USE_AMP flag in the cache- and gic-sources, as well as some boot-relevant assembler files but not in the xilffs- nor sdps-libs.

I'm think as well, that something is going on with the GIC. Maybe an interrupt needs to be  mapped to CPU1 but that's just a wild guess.

Did you eventually find a solution to the issue?

Thanks! Alex

0 Kudos
Reply
a.oerder1
Visitor
Visitor
1,033 Views
Registered: ‎01-17-2020

Having tried to remap SDIO0-interrupt (56U) to CPU1 explicitly didn't work for me. Also xsdps.h's header says that the library is not running in interrupt-mode.

 

// Features not supported include - card write protect, password setting,
// lock/unlock, interrupts, SDMA mode, programmed I/O mode and
// 64-bit addressed ADMA2, erase/pre-erase commands.

 

 

0 Kudos
Reply
jzartman
Observer
Observer
1,017 Views
Registered: ‎06-18-2019

Yes. I solved this problem. I will post a solution sometime today.

 

a.oerder1
Visitor
Visitor
1,000 Views
Registered: ‎01-17-2020
Awesome - already thanks in advance!
jzartman
Observer
Observer
956 Views
Registered: ‎06-18-2019

Alright, bear with me on this because it's been a while since I had this issue. The issue with the SD card not being able to run on the second core of the processor has to do with the L2 cache being shared between the two cores. I dug through the code to see exactly where the USEAMP flag breaks the SD card functionality and I believe it was somewhere in the cache control functions (xil_cache.h or something like that). ANYWAY, the only thing (I think) that you need to change in the code that I originally posted is to add something like this:

  // Disables L2 Cache on APP1 RAM (0x00200000 - 0x00500000)
  Xil_SetTlbAttributes(0x00200000, 0x14de6);
  Xil_SetTlbAttributes(0x00300000, 0x14de6);
  Xil_SetTlbAttributes(0x00400000, 0x14de6);

I have notes that I took on the different attributes but I'd have to dig a little to find the actual Xilinx documents that I referenced. Each call of Xil_SetTlbAttributes applies to a 1 MB block of memory starting from the address specified by the first argument. This needs to be applied to the DDR addresses used by the second core of the processor. The addresses need to match whatever is in the linker script of the second processor core.

xil_mmu.h also does not need to be included.

View solution in original post

Tags (1)
a.oerder1
Visitor
Visitor
915 Views
Registered: ‎01-17-2020

Hi, sure! With disabling the Cache for the whole memory region of CPU1 I can mount the filesystem as well, however I cannot locate files as f_open returns FR_NO_FILE. I will dig into this and keep this thread posted on any findings.

0 Kudos
Reply
jzartman
Observer
Observer
898 Views
Registered: ‎06-18-2019
Awesome. Yeah, the program I posted requires that the SD card be formatted to FAT32 beforehand. That may be the cause of your issue. The xilfs library has a format function, but it was adding around 10 seconds to program execution.

Also, keep in mind that this method only disables L2 cache for core 1, and L1 is still used. If I remember correctly, the xil_cache.h only offers methods for disabling cache globally.
0 Kudos
Reply
Rmccarty
Adventurer
Adventurer
868 Views
Registered: ‎09-05-2020

There are also seperate functions for enabling the L1 caches only.

0 Kudos
Reply
brandnj20fiber
Observer
Observer
765 Views
Registered: ‎02-15-2020
 // Disables L2 Cache on APP1 RAM (0x00200000 - 0x00500000)
  Xil_SetTlbAttributes(0x00200000, 0x14de6);
  Xil_SetTlbAttributes(0x00300000, 0x14de6);
  Xil_SetTlbAttributes(0x00400000, 0x14de6);

This is great!

Does anyone know the argument for L1 cache instead of L2? I need to leave the caches alone on CPU0 but disable them all for CPU1..

I've got AMP working too but when I enable the SD cards from CPU1 it breaks the code running on CPU0....

0 Kudos
Reply
jzartman
Observer
Observer
752 Views
Registered: ‎06-18-2019

I can provide links on Monday. I have notes, but I would need to dig a little in order to provide references. Search for TLB attributes in the documentation in the meantime if you need an immediate answer. I believe one of the documents was named something on the lines of Zynq Software Developer Manual, but that's just off the top of my head.

0 Kudos
Reply