Porting Openware to Daisy

Getting a usable bootloader turned out too complicated. It can’t be done with the simpler approach of execution from QSPI, because it can either read and execute code or be written to, but not both both at once. Using QSPI as ROM and uploading data to external memory is another approach suggested by ST. This should work, but initialization hangs when it resets RCC clock. I’m not sure how to solve this yet, plus it seems to require initializing FMC with registers before HAL is started.

So for now I will try to fit everything in flash - currently at 88k out of 128k. In order to allocate math LUTS I’ve written a script to convert binary data to resources (i.e. add resource header and use little endian format). It can also parse data from C headers, so I can convert pow/log tables.

Once I confirm that this script works correctly, I will add some code to preload data from resources to RAM. And that should be the last major step left till FW is usable.

Made some experiments with using ITCM/DTCM memory. ITCM can be used for loading most common code via linker script + custom startup, confirmed that this works. DTCM will store data/bss/stack and maybe I will use half of it for fast heap section like it was done for CCM on older devices.

Figured out that a nice progress bar would be useful, especially since we can have larger patches/resources (up to 512k in theory)

Guess I’ll be porting this to Magus too.

Made UI page for gates state visualization:

Output state can be triggered with encoder click

Made comparison for CPU usage of stock patches from Magus running on Daisy:

Kickbox: 15% vs 55%
LorenzFM: 8% vs 27%

So around x3.5 better CPU performance. This is with cache enabled, obviously.

My idea to write bootloader based on firmware header worked, it can boot finally. Remaining minor issues:

  • roll back some stuff intended to use LUTs from resources - this is no longer needed

  • find a way to store settings only when no patch is running - either defer saving until patch is stopped or pause it. this is to prevent read errors when QSPI is not in memory mapped mode

  • there seems to be some issue when default parameter values are set from the patch. might be a bug introduced in UI controller.

  • debug build only runs if I run it when flashing with the programmer, but not on reboot. I suspect it could be related to semihosting being enabled.

  • also, debug build gets stuck when booting if the USB cable is plugged

It looks like I’ve fixed all outstanding issues. The USB cable thing required turning off OTG_FS_IRQn in bootloader before jumping to application, looks like not doing this causes an interrupt storm that prevents device from booting. I don’t think anything similar is happening on F4 devices. I’m using the same thing I’ve seen in Magus to set VTOR - SCB->VTOR = (uint32_t)&_ISR_VECTOR; and made sure that it gets changed, so not sure why is old interrupt firing before it’s enabled by application itself.

@mars I’ll probably announce this on Daisy forums within a week from now and make unofficial firmware releases. There would likely appear a certain number of clueless users here after that. Let me know if you think that it’s ok. I’ll start cleaning up final code version and preparing PRs once the dust settles.

Cool, I’ll have to give it a go - haven’t unpacked my Daisy yet!

I think it’s better to keep discussions about running OpenWare on the Daisy platform over on the Daisy forum, as it is really for Daisy users.

I’ve had some weirdness switching context on the H7 too, it seems a bit finicky sometimes. They recommend clearing pending interrupts before jumping, see e.g. ST Community

and you’ll want to flush the cache first, too!

Yeah, I agree that discussing port should be done on the other forum, but I’m not so sure about people writing patches and having typical newbie questions. It makes sense to consolidate such info here. So if that doesn’t sound like a bad idea, I could suggest them to ask questions about writing patches here (or do the opposite if that’s inconvenient).

So which device have you got? This port is for Patch specifically. I imagine it won’t take much effort to make a separate project for using it with just Seed. Or it’s possible to add an encoder and a SSD1309 OLED to “upgrade” it to something that can be used on a breadboard with current FW (there’s support for building it with only first SAI).

What’s interesting about your link is the part setting “NVIC->ICER” - I think it wasn’t present in the sample bootloader app from Cube that I’ve seen. I will test with this code instead of disabling only USB interrupt, but this looks more reliable.

As for cache, I’ve decided it’s better not to enable it in bootloader, it normally takes a fraction of second to load FW and I don’t want to risk any surprises from caching at this stage.

Built without problems all Fascination Machine patches. MCU usage is 20-33% depending on the patch.

Unfortunately I’m getting hardfaults 1-2 times per hour, it wasn’t happening with simpler patches (or maybe I didn’t let FW run long enough to notice this). I think this could be something cache-related.

I’ve caught assertion error a few times in FascinationMachine patches (or at least FM IV) after patch runs for some time: "Heavy assertion failed in void __hv_tabwrite_f(SignalTabwr line 40". This is raised by the following line:

  hv_assert((o->head + HV_N_SIMD) <= hTable_getSize(o->table)); // assert that the table bounds are respected

I suspect this may be an issue with HVCC itself, so will try to run the same patches on Magus for a while to see if can be reproduced.

Agreed - patch discussions are very welcome here!

It looks like the issue was solved after I’ve disabled instruction execution from SDRAM in MPU settings - I think this disabled instruction prefetch that was causing some data to be interpreted as broken code. We don’t execute code from SDRAM, so this is probably the proper way to configure memory access. No issues after several hours yesterday with the same code.

Speaking of code patches, I will be making PR with a few updates for OwlProgram soon - for multi-channel audio (obviously needed for Daisy’s quad channels, but it can parse and process other configurations based on program vector audio format field), H7 compilation and device-specific compilation settings for Daisy. I assume that there’s no multi-channel audio support there yet (i.e. for Noctua), or did I miss it somehow?

I’ve also tested some non-trivial patches in other languages (a very nice reverb in Faust and less nice and more CPU-hungry one compiled from Gen).

I do have an experimental multi-channel branch for Noctua. Also using the audio format to communicate number of channels.
Let me push it - here it is : https://github.com/pingdynasty/OwlProgram/tree/feature/notcua-multichannel

I’ve been planning some more multi-channel changes, on the firmware side: I’d like to dynamically allocate buffers for only as many channels as a patch uses. So the firmware needs to be able to find out from the patch how many channels it wants, before initialising it.
The reasoning behind it is that, in one example, with USB audio we can let the patch do the routing between USB channels and physical hardware channels. So if e.g. the Magus firmware supports 2 codec channels, plus 2 channels in/out over USB, then the patch could see up to 4 channels. But for normal stereo patches, there’s no need to allocate the extra buffers.

Ok, I think I will try to use this for Daisy. I’ve made a class similar to SampleBuffer, just not using a hardcoded value of 2 channels. But like you say, dynamic buffer allocation is more interesting considering USB audio.

I wonder if we can have changes to audio format to make parsing it more consistent. I’ve used the following macros:

This would eliminate long switch expressions that list every format/number of channels we want to support in PatchProcessor. It’s not compatible with how 16/24 bit formats are defined currently. However, we can detect case when patch runs on old FW with those format, because they would be parsed as having 0 channels (0x10/0x18).

Yes agreed, this is where I was heading with this branch before I got distracted by other stuff.

Another thing we can easily do is correct for reverse polarity, by changing the multiplier that should be used.

I was planning to do a bit of work in this area next month when I pick up the Noctua again. If you want to push on in the meantime that’s great!

It’s a bit radical, but I wonder if decoding data in patch rather than firmware will end up practical as more audio sources are added. I mean that USB audio could be using different format than codec. Besides that, I will be trying to get SD card to work on Daisy Patch - and that could include streaming audio from card as extra channels (which could come from float values in WAV files). Maybe we need an extra format for float channels that would let FW handle all data conversion?

Right so you mean the firmware would provide the in/out float arrays, for replacement processing?

Part of the reasoning of doing this in the patch was to support fixed-point patches. But, eight years later, we’ve not really got any of those :slight_smile:

mmm I like this idea

I suppose people use fixed point not because it’s fun, but mainly due to running on powerful DSP hardware that lacks an FPU :wink: So not surprising that there’s no interest in this on STM32 MCUs.

If necessary, fixed point could be supported by following the same approach with separate fields for format/number of channels - it would be just an extra set of formats for FP with different bit depths. Realistically it’s probably not very useful.

I’ve ran into strange issue when running code from Noctua branch. When split32 runs this code, audio turns into noise in Faust patches:

    const float mul = 1.0f/MULTIPLIER_23B;
...
	buffers[j][i] = *input++ * mul;

But restoring the way it used to work in develop branch gives me the correct audio:

    const float mul = 1.0f/MULTIPLIER_31B;
...
        buffers[j][i] = (*input++ << 8) * mul;

Am I losing sanity? Could it be something related to using I2S MSB format by this codec?

Other than this issue, looks like I’ve got that branch working on Daisy.