Skip to content

Commit

Permalink
Add back Serial USB logging with SRAM optimizations.
Browse files Browse the repository at this point in the history
This commit is derived from code from @morio across the following
commits plus my own adjustments for the BlueSCSI platform:
Output log over serial USB
ZuluSCSI/ZuluSCSI-firmware@573dc60
Fix out SRAM compile time issue
ZuluSCSI/ZuluSCSI-firmware@30df3aa
Adjust prefetch buffer to fix SRAM overflow
ZuluSCSI/ZuluSCSI-firmware@9f61b3c
Get PlatformIO debug to work on RP2040 MCUs
ZuluSCSI/ZuluSCSI-firmware@d72012b

Co-authored-by: Morio <morio.earth@gmail.com>
  • Loading branch information
erichelgeson and morio committed Dec 13, 2023
1 parent 28f6de1 commit 34da988
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 62 deletions.
53 changes: 37 additions & 16 deletions lib/BlueSCSI_platform_RP2040/BlueSCSI_platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@
#include <hardware/flash.h>
#include <hardware/structs/xip_ctrl.h>
#include <hardware/structs/usb.h>
#ifdef MBED
#include <platform/mbed_error.h>
#include <USB/PluggableUSBSerial.h>
#ifdef ENABLE_AUDIO_OUTPUT
#include "audio.h"
#endif

#ifndef __MBED__
# include <SerialUSB.h>
# include <class/cdc/cdc_device.h>
#else
# include <platform/mbed_error.h>
# include <USB/PluggableUSBSerial.h>
#endif // __MBED__

#include <pico/multicore.h>
#include "scsi_accel_rp2040.h"
#include "hardware/i2c.h"
Expand Down Expand Up @@ -282,6 +289,11 @@ void platform_late_init()
gpio_conf(scsi_pins.IN_ATN, GPIO_FUNC_SIO, false, false, false, true, false);
gpio_conf(scsi_pins.IN_RST, GPIO_FUNC_SIO, true, false, false, true, false);


#ifndef __MBED__
Serial.begin();
#endif // __MBED__

#ifdef ENABLE_AUDIO_OUTPUT
// one-time control setup for DMA channels and second core
audio_setup();
Expand Down Expand Up @@ -416,11 +428,27 @@ void mbed_error_hook(const mbed_error_ctx * error_context)
// also starts calling this after 2 seconds.
// This ensures that log messages get passed even if code hangs,
// but does not unnecessarily delay normal execution.
#ifdef MBED
static void usb_log_poll()
{
static uint32_t logpos = 0;
#ifndef __MBED__
if (Serial.availableForWrite())
{
// Retrieve pointer to log start and determine number of bytes available.
uint32_t available = 0;
const char *data = log_get_buffer(&logpos, &available);
// Limit to CDC packet size
uint32_t len = available;
if (len == 0) return;
if (len > CFG_TUD_CDC_EP_BUFSIZE) len = CFG_TUD_CDC_EP_BUFSIZE;

// Update log position by the actual number of bytes sent
// If USB CDC buffer is full, this may be 0
uint32_t actual = 0;
actual = Serial.write(data, len);
logpos -= available - actual;
}
#else
if (_SerialUSB.ready())
{
// Retrieve pointer to log start and determine number of bytes available.
Expand All @@ -438,8 +466,8 @@ static void usb_log_poll()
_SerialUSB.send_nb((uint8_t*)data, len, &actual);
logpos -= available - actual;
}
#endif // __MBED__
}
#endif

// Use ADC to implement supply voltage monitoring for the +3.0V rail.
// This works by sampling the temperature sensor channel, which has
Expand Down Expand Up @@ -520,13 +548,11 @@ static void watchdog_callback(unsigned alarm_num)
{
g_watchdog_timeout -= 1000;

#ifdef MBED
if (g_watchdog_timeout < WATCHDOG_CRASH_TIMEOUT - 1000)
{
// Been stuck for at least a second, start dumping USB log
usb_log_poll();
}
#endif

if (g_watchdog_timeout <= WATCHDOG_CRASH_TIMEOUT - WATCHDOG_BUS_RESET_TIMEOUT)
{
Expand Down Expand Up @@ -573,9 +599,8 @@ static void watchdog_callback(unsigned alarm_num)
p += 4;
}

#ifdef MBED
usb_log_poll();
#endif

platform_emergency_log_save();

platform_boot_to_main_firmware();
Expand Down Expand Up @@ -613,20 +638,17 @@ void platform_reset_watchdog()
g_watchdog_initialized = true;
}

#ifdef MBED
// USB log is polled here also to make sure any log messages in fault states
// get passed to USB.
usb_log_poll();
#endif
}

// Poll function that is called every few milliseconds.
// Can be left empty or used for platform-specific processing.
void platform_poll()
{
#ifdef MBED
usb_log_poll();
#endif

adc_poll();

#ifdef ENABLE_AUDIO_OUTPUT
Expand Down Expand Up @@ -692,15 +714,14 @@ bool platform_rewrite_flash_page(uint32_t offset, uint8_t buffer[PLATFORM_FLASH_
return false;
}
}

#ifdef MBED
#ifdef __MBED__
if (NVIC_GetEnableIRQ(USBCTRL_IRQn))
{
log("Disabling USB during firmware flashing");
NVIC_DisableIRQ(USBCTRL_IRQn);
usb_hw->main_ctrl = 0;
}
#endif
#endif // __MBED__

debuglog("Writing flash at offset ", offset, " data ", bytearray(buffer, 4));
assert(offset % PLATFORM_FLASH_PAGE_SIZE == 0);
Expand Down
2 changes: 1 addition & 1 deletion lib/BlueSCSI_platform_RP2040/rp2040.ld
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
MEMORY
{
FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 352k
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 240k /* Leave space for pico-debug */
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k /* Leave space for pico-debug */
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
}
Expand Down
20 changes: 19 additions & 1 deletion lib/SCSI2SD/src/firmware/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,32 @@
//
// You should have received a copy of the GNU General Public License
// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
#ifndef SCSI2SD_LOG_H
#define SCSI2SD_LOG_H
#include <stdbool.h>


#ifdef __cplusplus
extern "C" {
#endif

extern bool g_log_debug;

extern void log_buf(const unsigned char *buf, unsigned long size);
extern void log_f(const char *format, ...);

extern void dbgmsg_buf(const unsigned char *buf, unsigned long size);
extern void dbgmsg_f(const char *format, ...);

// check if debug is enabled before calling the logging function
#define DBGMSG_BUF(buf, size) \
if (g_log_debug) {dbgmsg_buf(buf, size);}

#define DBGMSG_F(format, ...) \
if (g_log_debug) {dbgmsg_f(format, __VA_ARGS__);}

#ifdef __cplusplus
}
#endif
#endif

#endif // SCSI2SD_LOG_H
62 changes: 20 additions & 42 deletions lib/SCSI2SD/src/firmware/network.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
#include "config.h"
#include "network.h"

extern bool g_log_debug;

static bool scsiNetworkEnabled = false;

struct scsiNetworkPacketQueue {
Expand Down Expand Up @@ -104,10 +102,7 @@ int scsiNetworkCommand()
uint8_t command = scsiDev.cdb[0];
uint8_t cont = (scsiDev.cdb[5] == 0x80);

if (g_log_debug)
{
log_f("in scsiNetworkCommand with command 0x%02x (size %d)", command, size);
}
DBGMSG_F("------ in scsiNetworkCommand with command 0x%02x (size %d)", command, size);

switch (command) {
case 0x08:
Expand Down Expand Up @@ -140,10 +135,7 @@ int scsiNetworkCommand()
psize = size - 6;
}

if (g_log_debug)
{
log_f("%s: sending packet[%d] to host of size %zu + 6", __func__, scsiNetworkInboundQueue.readIndex, psize);
}
DBGMSG_F("%s: sending packet[%d] to host of size %zu + 6", __func__, scsiNetworkInboundQueue.readIndex, psize);

scsiDev.dataLen = psize + 6; // 2-byte length + 4-byte flag + packet
memcpy(scsiDev.data + 6, scsiNetworkInboundQueue.packets[scsiNetworkInboundQueue.readIndex], psize);
Expand All @@ -162,10 +154,7 @@ int scsiNetworkCommand()
// more data to read?
scsiDev.data[5] = (scsiNetworkInboundQueue.readIndex == scsiNetworkInboundQueue.writeIndex ? 0 : 0x10);

if (g_log_debug)
{
log_buf(scsiDev.data, scsiDev.dataLen);
}
DBGMSG_BUF(scsiDev.data, scsiDev.dataLen);
}

// DaynaPort driver needs a delay between reading the initial packet size and the data so manually do two transfers
Expand Down Expand Up @@ -217,10 +206,14 @@ int scsiNetworkCommand()
parityError = 0;
scsiRead(scsiDev.data, size, &parityError);

if (g_log_debug)
if (parityError)
{
log_f("%s: read packet from host of size %zu - %d (parity error %d)", __func__, size, (cont ? 4 : 0), parityError);
log_buf(scsiDev.data, size);
DBGMSG_F("%s: read packet from host of size %zu - %d (parity error %d)", __func__, size, (cont ? 4 : 0), parityError);
DBGMSG_F(scsiDev.data, size);
}
else
{
DBGMSG_F("------ %s: read packet from host of size %zu - %d", __func__, size, (cont ? 4 : 0));
}

if (cont)
Expand Down Expand Up @@ -253,11 +246,8 @@ int scsiNetworkCommand()
parityError = 0;
scsiRead(scsiDev.data, size, &parityError);

if (g_log_debug)
{
log_f("%s: adding multicast address %02x:%02x:%02x:%02x:%02x:%02x", __func__,
DBGMSG_F("%s: adding multicast address %02x:%02x:%02x:%02x:%02x:%02x", __func__,
scsiDev.data[0], scsiDev.data[1], scsiDev.data[2], scsiDev.data[3], scsiDev.data[4], scsiDev.data[5]);
}

platform_network_add_multicast_address(scsiDev.data);

Expand All @@ -269,20 +259,16 @@ int scsiNetworkCommand()
// toggle interface
if (scsiDev.cdb[5] & 0x80)
{
if (g_log_debug)
{
log_f("%s: enable interface", __func__);
}

DBGMSG_F("%s: enable interface", __func__);
scsiNetworkEnabled = true;
memset(&scsiNetworkInboundQueue, 0, sizeof(scsiNetworkInboundQueue));
memset(&scsiNetworkOutboundQueue, 0, sizeof(scsiNetworkOutboundQueue));
}
else
{
if (g_log_debug)
{
log_f("%s: disable interface", __func__);
}

DBGMSG_F("%s: disable interface", __func__);
scsiNetworkEnabled = false;
}
break;
Expand All @@ -303,10 +289,7 @@ int scsiNetworkCommand()

// custom wifi commands all using the same opcode, with a sub-command in cdb[2]
case SCSI_NETWORK_WIFI_CMD:
if (g_log_debug)
{
log_f("in scsiNetworkCommand with wi-fi command 0x%02x (size %d)", scsiDev.cdb[1], size);
}
DBGMSG_F("in scsiNetworkCommand with wi-fi command 0x%02x (size %d)", scsiDev.cdb[1], size);

switch (scsiDev.cdb[1]) {
case SCSI_NETWORK_WIFI_CMD_SCAN:
Expand Down Expand Up @@ -404,11 +387,8 @@ int scsiNetworkCommand()
parityError = 0;
scsiRead((uint8_t *)&req, sizeof(req), &parityError);

if (g_log_debug)
{
log_f("%s: read join request from host:", __func__);
log_buf(scsiDev.data, size);
}
DBGMSG_F("%s: read join request from host:", __func__);
DBGMSG_BUF(scsiDev.data, size);

platform_network_wifi_join(req.ssid, req.key);

Expand All @@ -433,8 +413,7 @@ int scsiNetworkEnqueue(const uint8_t *buf, size_t len)

if (len + 4 > sizeof(scsiNetworkInboundQueue.packets[0]))
{
if (g_log_debug)
log_f("%s: dropping incoming network packet, too large (%zu > %zu)", __func__, len, sizeof(scsiNetworkInboundQueue.packets[0]));
DBGMSG_F("%s: dropping incoming network packet, too large (%zu > %zu)", __func__, len, sizeof(scsiNetworkInboundQueue.packets[0]));
return 0;
}

Expand All @@ -454,8 +433,7 @@ int scsiNetworkEnqueue(const uint8_t *buf, size_t len)

if (scsiNetworkInboundQueue.writeIndex == scsiNetworkInboundQueue.readIndex)
{
if (g_log_debug)
log_f("%s: dropping packets in ring, write index caught up to read index", __func__);
DBGMSG_F("%s: dropping packets in ring, write index caught up to read index", __func__);
}

return 1;
Expand Down
14 changes: 13 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,22 @@ platform_packages = platformio/toolchain-gccarmnoneeabi@1.100301.220327
framework = arduino
board = rpipicow
board_build.core = earlephilhower
upload_protocol = picoprobe
debug_tool = cmsis-dap ; new picoprobe.uf2's emulate cmsis-dap
; extra_scripts = src/build_bootloader.py
; ldscript_bootloader = lib/BlueSCSI_platform_RP2040/rp2040_btldr.ld
lib_deps =
SdFat=https://github.com/BlueSCSI/SdFat#2.2.0-gpt
minIni
BlueSCSI_platform_RP2040
SCSI2SD
CUEParser
debug_build_flags =
-O2 -ggdb -g3
; The values can be adjusted down to get a debug build to fit in to SRAM
-DLOGBUFSIZE=1024
-DSCSI2SD_BUFFER_SIZE=57344
-DPREFETCH_BUFFER_SIZE=6144
build_flags =
-O2 -Isrc -ggdb -g3
-Wall -Wno-sign-compare -Wno-ignored-qualifiers
Expand All @@ -32,9 +42,11 @@ build_flags =
-DENABLE_DEDICATED_SPI=1
-DHAS_SDIO_CLASS
-DUSE_ARDUINO=1
-DNO_USB=1
-DPICO_DEFAULT_I2C_SDA_PIN=16
-DPICO_DEFAULT_I2C_SCL_PIN=17
; -DLOGBUFSIZE=8192
; -DPREFETCH_BUFFER_SIZE=6144
; -DSCSI2SD_BUFFER_SIZE=57344

; Experimental Audio build
; Rquires seperate hardware and overclock.
Expand Down

0 comments on commit 34da988

Please sign in to comment.