소스 검색

Merge pull request #170 from ZuluSCSI/improve_error_recovery

Improve error recovery
Alex Perez 2 년 전
부모
커밋
24671b1c27

+ 4 - 0
lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_platform.cpp

@@ -319,6 +319,8 @@ void show_hardfault(uint32_t *sp)
     logmsg("CRASH!");
     logmsg("Platform: ", g_platform_name);
     logmsg("FW Version: ", g_log_firmwareversion);
+    logmsg("scsiDev.cdb: ", bytearray(scsiDev.cdb, 12));
+    logmsg("scsiDev.phase: ", (int)scsiDev.phase);
     logmsg("CFSR: ", cfsr);
     logmsg("SP: ", (uint32_t)sp);
     logmsg("PC: ", pc);
@@ -396,6 +398,8 @@ void __assert_func(const char *file, int line, const char *func, const char *exp
     logmsg("ASSERT FAILED!");
     logmsg("Platform: ", g_platform_name);
     logmsg("FW Version: ", g_log_firmwareversion);
+    logmsg("scsiDev.cdb: ", bytearray(scsiDev.cdb, 12));
+    logmsg("scsiDev.phase: ", (int)scsiDev.phase);
     logmsg("Assert failed: ", file , ":", line, " in ", func, ":", expr);
 
     uint32_t *p = (uint32_t*)((uint32_t)&dummy & ~3);

+ 8 - 0
lib/ZuluSCSI_platform_RP2040/ZuluSCSI_platform.cpp

@@ -324,6 +324,8 @@ void mbed_error_hook(const mbed_error_ctx * error_context)
     logmsg("error_status: ", (uint32_t)error_context->error_status);
     logmsg("error_address: ", error_context->error_address);
     logmsg("error_value: ", error_context->error_value);
+    logmsg("scsiDev.cdb: ", bytearray(scsiDev.cdb, 12));
+    logmsg("scsiDev.phase: ", (int)scsiDev.phase);
 
     uint32_t *p = (uint32_t*)((uint32_t)error_context->thread_current_sp & ~3);
     for (int i = 0; i < 8; i++)
@@ -420,7 +422,11 @@ static void watchdog_callback(unsigned alarm_num)
         {
             logmsg("--------------");
             logmsg("WATCHDOG TIMEOUT, attempting bus reset");
+            logmsg("Platform: ", g_platform_name);
+            logmsg("FW Version: ", g_log_firmwareversion);
             logmsg("GPIO states: out ", sio_hw->gpio_out, " oe ", sio_hw->gpio_oe, " in ", sio_hw->gpio_in);
+            logmsg("scsiDev.cdb: ", bytearray(scsiDev.cdb, 12));
+            logmsg("scsiDev.phase: ", (int)scsiDev.phase);
 
             uint32_t *p = (uint32_t*)__get_PSP();
             for (int i = 0; i < 8; i++)
@@ -442,6 +448,8 @@ static void watchdog_callback(unsigned alarm_num)
             logmsg("Platform: ", g_platform_name);
             logmsg("FW Version: ", g_log_firmwareversion);
             logmsg("GPIO states: out ", sio_hw->gpio_out, " oe ", sio_hw->gpio_oe, " in ", sio_hw->gpio_in);
+            logmsg("scsiDev.cdb: ", bytearray(scsiDev.cdb, 12));
+            logmsg("scsiDev.phase: ", (int)scsiDev.phase);
 
             uint32_t *p = (uint32_t*)__get_PSP();
             for (int i = 0; i < 8; i++)

+ 10 - 2
lib/ZuluSCSI_platform_RP2040/scsiPhy.cpp

@@ -220,13 +220,21 @@ extern "C" uint32_t scsiEnterPhaseImmediate(int phase)
         scsiLogPhaseChange(phase);
 
         // Select between synchronous vs. asynchronous SCSI writes
+        bool syncstatus = false;
         if (scsiDev.target->syncOffset > 0 && (g_scsi_phase == DATA_IN || g_scsi_phase == DATA_OUT))
         {
-            scsi_accel_rp2040_setSyncMode(scsiDev.target->syncOffset, scsiDev.target->syncPeriod);
+            syncstatus = scsi_accel_rp2040_setSyncMode(scsiDev.target->syncOffset, scsiDev.target->syncPeriod);
         }
         else
         {
-            scsi_accel_rp2040_setSyncMode(0, 0);
+            syncstatus = scsi_accel_rp2040_setSyncMode(0, 0);
+        }
+
+        if (!syncstatus)
+        {
+            // SCSI DMA was not idle, we are in some kind of error state, force bus reset
+            scsiDev.resetFlag = 1;
+            return 0;
         }
 
         if (phase < 0)

+ 7 - 2
lib/ZuluSCSI_platform_RP2040/scsi_accel_rp2040.cpp

@@ -956,9 +956,13 @@ void scsi_accel_rp2040_init()
     irq_set_enabled(DMA_IRQ_0, true);
 }
 
-void scsi_accel_rp2040_setSyncMode(int syncOffset, int syncPeriod)
+bool scsi_accel_rp2040_setSyncMode(int syncOffset, int syncPeriod)
 {
-    assert(g_scsi_dma_state == SCSIDMA_IDLE);
+    if (g_scsi_dma_state != SCSIDMA_IDLE)
+    {
+        logmsg("ERROR: SCSI DMA was in state ", (int)g_scsi_dma_state, " when changing sync mode, forcing bus reset");
+        return false;
+    }
 
     if (syncOffset != g_scsi_dma.syncOffset || syncPeriod != g_scsi_dma.syncPeriod)
     {
@@ -1051,4 +1055,5 @@ void scsi_accel_rp2040_setSyncMode(int syncOffset, int syncPeriod)
         }
     }
 
+    return true;
 }

+ 2 - 1
lib/ZuluSCSI_platform_RP2040/scsi_accel_rp2040.h

@@ -30,7 +30,8 @@ void scsi_accel_rp2040_init();
 // Set SCSI access mode for synchronous transfers
 // Setting syncOffset = 0 enables asynchronous SCSI.
 // Setting syncOffset > 0 enables synchronous SCSI.
-void scsi_accel_rp2040_setSyncMode(int syncOffset, int syncPeriod);
+// Returns false if busy, caller should issue bus reset to recover.
+bool scsi_accel_rp2040_setSyncMode(int syncOffset, int syncPeriod);
 
 // Queue a request to write data from the buffer to SCSI bus.
 // This function typically returns immediately and the request will complete in background.

+ 1 - 1
src/ZuluSCSI_disk.cpp

@@ -1866,7 +1866,7 @@ static void diskDataIn()
             prefetch_sectors = img_sector_count - g_scsi_prefetch.sector;
         }
 
-        while (!scsiIsWriteFinished(NULL) && prefetch_sectors > 0)
+        while (!scsiIsWriteFinished(NULL) && prefetch_sectors > 0 && !scsiDev.resetFlag)
         {
             // Check if prefetch buffer is free
             g_disk_transfer.buffer = g_scsi_prefetch.buffer + g_scsi_prefetch.bytes;