05-28-2020 02:02 PM - edited 05-29-2020 09:23 AM
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 ...
10-22-2020 10:58 AM - edited 10-22-2020 10:59 AM
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.
06-04-2020 06:46 PM
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...
10-22-2020 02:54 AM
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
10-22-2020 03:44 AM
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.
10-22-2020 04:57 AM
Yes. I solved this problem. I will post a solution sometime today.
10-22-2020 05:40 AM
10-22-2020 10:58 AM - edited 10-22-2020 10:59 AM
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.
10-23-2020 12:58 AM
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.
10-23-2020 06:26 AM
10-24-2020 01:47 AM
There are also seperate functions for enabling the L1 caches only.
10-31-2020 11:02 AM
// 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....
10-31-2020 12:29 PM
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.