Wiznet W7500 flash programming
W7500 is a nice little MCU from Wiznet with a built-in hardware TCP/IP stack and Ethernet MAC. You can get quite far with your IoT application on a Cortex-M0 running at 48 MHz when the networking is offloaded in hardware. The device begins to show its age in 2023 (it was released around 2016). There is no crypto acceleration whatsoever, no AES. Only an RNG is available. I think that modern TLS is practically impossible but some lighter cryptography should be possible. Nevertheless, if you can put the device on an isolated VLAN the chip can still be useful today.
There is also a companion device W7500P with also the PHY built-in so all that you need to implement networking on your board is this chip and an Ethernet jack with magnetics (plus the passives and sensors/actuators that would be needed anyway).
The documentation could always be better but the examples
really hit a sweet spot. You don't have to download gigabytes of IDEs and SDKs to build a simple project with
The only place I hit a snag was programming of the flash. The device has some extra sectors that can be used for example to store settings. Part of the flash handling functions are in ROM and all that you get is this piece of code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
What does it do?! It is just a function call to something magical at the address
In my case the CPU crashed with a hard fault when this code was called (or shortly after...).
Additionally, there is an
erratum for the flash that requires
clocking from the internal RC oscillator when executing flash operations.
A call to ROM... is not the easiest thing to debug. I started by switching to the internal clock but the problem
persisted. Then I had a look around the lines in
FLASH_IAP() that modify the NVIC.
I think that the original author tried to block the interrupts when the ROM function is called.
In Cortex-M0 the
ISPR is the interrupt set pending register. It can be read to find out
pending interrupts but it can only be written with ones to set a particular interrupt.
There is a companion
ICPR clear register. I don't think the intent was to make all interrupts
active and then call the ROM.
I hoped that the ROM function did not do anything with the interrupts so I just wrapped the call with
__enable_irq() like this:
1 2 3 4 5 6 7 8 9
To my (not) surprise the code worked just fine. Flash was modified as I expected it to be. The last step was to add the clock switch erratum. I decided to switch the core clock to internal RC without reconfiguring the PLL. The final code is:
1 2 3 4 5 6 7 8 9 10 11