Pārlūkot izejas kodu

Read BRFS from SPI Flash in QSPI mode, df util added to OS, clear command after boot, init script to compile and send all userbdos programs to newly formatted brfs

bart 7 mēneši atpakaļ
vecāks
revīzija
904815e900
5 mainītis faili ar 133 papildinājumiem un 35 dzēšanām
  1. 14 30
      BCC/BDOS/lib/brfs.c
  2. 73 5
      BCC/BDOS/lib/shell.c
  3. 16 0
      BCC/BDOS/lib/spiflash.c
  4. 30 0
      BCC/initBDOS.sh
  5. 0 0
      BCC/syncCsourceFiles.sh

+ 14 - 30
BCC/BDOS/lib/brfs.c

@@ -14,6 +14,7 @@ Implementing in BDOS on PCB v3:
 #define BRFS_RAM_STORAGE_ADDR 0x100000 // From 4th MiB
 
 // Addresses in SPI Flash
+#define SPIFLASH_MEMMAP_ADDR 0x800000
 // Note that each section should be in a different 4KiB sector in SPI Flash
 #define BRFS_SPIFLASH_SUPERBLOCK_ADDR 0xDF000 // One sector before FAT
 #define BRFS_SPIFLASH_FAT_ADDR 0xE0000 // Can be 32768 words (128KiB) for 32MiB of 256word blocks
@@ -1130,31 +1131,6 @@ struct brfs_dir_entry* brfs_stat(char* file_path)
   return (struct brfs_dir_entry*)-1;
 }
 
-/**
- * Check if a block has changed by comparing it to the flash, returns 1 if changed and 0 if not
- * Note: this is slow and should eventually be replaced by a list of changed blocks
- * block_idx: index of the block
-*/
-word brfs_check_block_changed(word block_idx)
-{
-  struct brfs_superblock* superblock = (struct brfs_superblock*) brfs_ram_storage;
-  word* data_block_addr = brfs_ram_storage + SUPERBLOCK_SIZE + superblock->total_blocks;
-
-  word spi_data_buffer[256];
-
-  if (superblock->words_per_block > 256)
-  {
-    uprintln("Error: words_per_block should be <= 256 for this function!");
-    return 0;
-  }
-
-  // Read block from flash, and enable bytes to word
-  spiflash_read_from_address(spi_data_buffer, BRFS_SPIFLASH_BLOCK_ADDR + block_idx * superblock->words_per_block, superblock->words_per_block, 1);
-
-  // Compare block to flash
-  return memcmp(data_block_addr + (block_idx * superblock->words_per_block), spi_data_buffer, superblock->words_per_block);
-}
-
 /**
  * Write the FAT table to SPI flash by performing three steps:
  * 1. Check which FAT entries have changed
@@ -1395,28 +1371,36 @@ word brfs_superblock_is_valid(struct brfs_superblock* superblock)
 
 /**
  * Read the superblock, FAT and data blocks from SPI flash
+ * Reads in QSPI mode and returns to SPI mode after reading
  * Returns 1 on success, or 0 on error
 */
 word brfs_read_from_flash()
 {
+  // Set QSPI memory mapped mode
+  spiflash_qspi();
+
   // Read superblock from flash
-  spiflash_read_from_address(brfs_ram_storage, BRFS_SPIFLASH_SUPERBLOCK_ADDR, SUPERBLOCK_SIZE, 1);
+  char* spi_flash_read_addr = (char*) SPIFLASH_MEMMAP_ADDR + (BRFS_SPIFLASH_SUPERBLOCK_ADDR >> 2);
+  memcpy(brfs_ram_storage, spi_flash_read_addr, SUPERBLOCK_SIZE);
 
   // Perform validity checks on superblock
   struct brfs_superblock* superblock = (struct brfs_superblock*) brfs_ram_storage;
   if (!brfs_superblock_is_valid(superblock))
   {
     uprintln("Error: superblock is not valid!");
+    spiflash_init(); // Return to SPI mode
     return 0;
   }
   
-  word* data_block_addr = brfs_ram_storage + SUPERBLOCK_SIZE + superblock->total_blocks;
-
   // Read FAT from flash
-  spiflash_read_from_address(brfs_ram_storage + SUPERBLOCK_SIZE, BRFS_SPIFLASH_FAT_ADDR, superblock->total_blocks, 1);
+  spi_flash_read_addr = (char*) SPIFLASH_MEMMAP_ADDR + (BRFS_SPIFLASH_FAT_ADDR >> 2);
+  memcpy(brfs_ram_storage + SUPERBLOCK_SIZE, spi_flash_read_addr, superblock->total_blocks);
 
   // Read data blocks from flash
-  spiflash_read_from_address(data_block_addr, BRFS_SPIFLASH_BLOCK_ADDR, superblock->total_blocks * superblock->words_per_block, 1);
+  word* data_block_addr = brfs_ram_storage + SUPERBLOCK_SIZE + superblock->total_blocks;
+  spi_flash_read_addr = (char*) SPIFLASH_MEMMAP_ADDR + (BRFS_SPIFLASH_BLOCK_ADDR >> 2);
+  memcpy(data_block_addr, spi_flash_read_addr, superblock->total_blocks * superblock->words_per_block);
 
+  spiflash_init(); // Return to SPI mode
   return 1;
 }

+ 73 - 5
BCC/BDOS/lib/shell.c

@@ -360,6 +360,70 @@ void shell_format_filesystem()
   brfs_write_to_flash();
 }
 
+/**
+ * Show filesystem usage
+*/
+void shell_show_fs_usage()
+{
+  struct brfs_superblock* superblock = (struct brfs_superblock*)brfs_ram_storage;
+  word total_blocks = superblock->total_blocks;
+  word block_size = superblock->words_per_block;
+
+  char* fat_addr = brfs_ram_storage + SUPERBLOCK_SIZE;
+
+  // Loop through FAT table and count free blocks
+  word free_blocks = 0;
+  word i = 0;
+  while (i < total_blocks)
+  {
+    if (fat_addr[i] == 0)
+    {
+      free_blocks++;
+    }
+    i++;
+  }
+
+  word used_blocks = total_blocks - free_blocks;
+  word used_space = used_blocks * block_size;
+  word free_space = free_blocks * block_size;
+  word total_space = total_blocks * block_size;
+
+  GFX_PrintConsole("Usage:\n");
+  GFX_PrintConsole("------\n");
+
+  GFX_PrintConsole("Used blocks : ");
+  GFX_PrintDecConsole(used_blocks);
+  GFX_PrintConsole("/");
+  GFX_PrintDecConsole(total_blocks);
+  GFX_PrintConsole("\n");
+  GFX_PrintConsole("Used space  : ");
+  GFX_PrintDecConsole(MATH_divU(used_space, 1000));
+  GFX_PrintConsole("/");
+  GFX_PrintDecConsole(MATH_divU(total_space, 1000));
+  GFX_PrintConsole(" kwords\n");
+
+  GFX_PrintConsole("\nFree space:\n");
+  GFX_PrintConsole("-----------\n");
+
+  GFX_PrintConsole("Free blocks : ");
+  GFX_PrintDecConsole(free_blocks);
+  GFX_PrintConsole("\n");
+  GFX_PrintConsole("Free space  : ");
+  GFX_PrintDecConsole(MATH_divU(free_space, 1000));
+  GFX_PrintConsole(" kwords\n");
+  
+
+  GFX_PrintConsole("\nBlocks:\n");
+  GFX_PrintConsole("-------\n");
+
+  GFX_PrintConsole("Total blocks: ");
+  GFX_PrintDecConsole(total_blocks);
+  GFX_PrintConsole("\n");
+  GFX_PrintConsole("Block size  : ");
+  GFX_PrintDecConsole(block_size);
+  GFX_PrintConsole(" words\n");
+}
+
 /**
  * Handle the command
 */
@@ -384,10 +448,6 @@ void shell_handle_command()
   {
     brfs_write_to_flash();
   }
-  else if (strcmp(shell_tokens[0], "read") == 0)
-  {
-    brfs_read_from_flash();
-  }
   else if (strcmp(shell_tokens[0], "dump") == 0)
   {
     // Dump FAT
@@ -397,6 +457,10 @@ void shell_handle_command()
   {
     shell_format_filesystem();
   }
+  else if (strcmp(shell_tokens[0], "df") == 0)
+  {
+    shell_show_fs_usage();
+  }
   // Attempt to run program both from local dir and from SHELL_BIN_PATH
   else if (!shell_run_program(0))
   {
@@ -412,13 +476,17 @@ void shell_handle_command()
 */
 void shell_init()
 {
+  // Clear screen by clearing window tables and resetting the cursor
+  GFX_clearWindowtileTable();
+  GFX_clearWindowpaletteTable();
+  GFX_cursor = 0;
+
   shell_clear_command();
   // Set path to root
   strcpy(shell_path, "/");
   shell_print_prompt();
 }
 
-
 /**
  * Main shell loop
 */

+ 16 - 0
BCC/BDOS/lib/spiflash.c

@@ -56,6 +56,22 @@ word spiflash_transfer(word dataByte)
   return retval;
 }
 
+// Disable manual operation and set SPI0 back to QSPI mode
+// This allows SPI content to be read directly from memory at high speeds
+// However, this disables writing and other manual operations
+void spiflash_qspi()
+{
+  // Send QSPI command
+  spiflash_begin_transfer();
+  spiflash_transfer(0xEB);
+  spiflash_end_transfer();
+
+  // Disable SPI0 (connects SPIreader.v and disconnects simpleSPI.v)
+  word *p = (word *) 0xC0272A; // Set address (SPI0 enable)
+  *p = 0; // Write value
+  delay(10);
+}
+
 // Initialize manual operation of SPI flash by enabling SPI0 and resetting the chip
 // This is needed to get out of continuous read mode and allow manual commands
 void spiflash_init()

+ 30 - 0
BCC/initBDOS.sh

@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# Script to initialize BDOS (as in an intitial setup) by uploading all the programs in userBDOS to the /bin directory
+
+MAINPATH=$(pwd)
+
+echo $MAINPATH
+
+# Create /bin directory
+echo "cd /" | python3 "$MAINPATH/../Programmer/sendCommand.py"
+sh uploadToBDOS.sh userBDOS/mkdir.c mkdir
+echo "mkdir /bin" | python3 "$MAINPATH/../Programmer/sendCommand.py"
+echo "cd /bin" | python3 "$MAINPATH/../Programmer/sendCommand.py"
+sleep 0.5
+
+# Upload all the programs in a very hardcoded way given the directory structure of the project
+cd userBDOS
+for j in $(find . -maxdepth 1 -type f -print)
+do
+    cd $MAINPATH
+    FNAME=$(basename $j)
+    # Remove extension from FNAME
+    FNAME="${FNAME%.*}"
+    # Remove leading ./
+    j="${j#./}"
+    bash uploadToBDOS.sh userBDOS/$j $FNAME
+    sleep 0.5
+done
+
+echo "rm /mkdir" | python3 "$MAINPATH/../Programmer/sendCommand.py"

+ 0 - 0
BCC/syncCfiles.sh → BCC/syncCsourceFiles.sh