2 February 2025
So I’ve had some time to think about it, and I think I will spend a little more time trying to better understand what exactly is going on with whatever it was that I did yesterday to make the chip reset itself on every other keystroke. It’s a bit ironic, as the whole point of this particular tangent was specifically to reset the device.
I’m going to build in a lot more debugging information into the code to help understand this present weirdness and also to be in a better position in the future to deal with it when it inevitably happens again.
The first thing is to add some code at the very beginning:
# *** debug *** check CSRs for exception information
csrr t0, mcause # cause of exception
csrr t1, mepc # address where violation occurred
csrr t2, mtval # exception value
csrr t3, mstatus # status
Then I did a bunch of other stuff, but it didn’t help. What I eventually found out was that I had neglected to configure the EXTI to use PB0 as the input to EXTI0. The default was PA0. That’s why the system reset itself on the second keystroke, because that’s the one that turned the LED on (active low LED) and toggling PA0 would generate the EXTI interrupt, resetting the system. I was able to confirm this by omitting only the LED toggle function, and all worked as expected.
So I set the appropriate bits in the External Interrupt Configuration Register AFIO_EXTICR1 to indicate that PB0 should be routed to EXTI, and for some reason it still didn’t work. Then I remembered that the AFIO controller has to have its peripheral clock enabled just like everything else. Once I added that to the list of the of PB2 peripheral clocks to enable, then everything works as expected.
Now… where was I? Oh, yes: testing the fake reset button. It still doesn’t work.
This time it is because the RM is wrong. Here are the values it indicates on p. 74:
00: xth pin of the PA pin.
10: xth pin of the PB pin.
11: xth pin of the PC pin.
Others: Reserved.
The default is 00, and this was certainly working when PA0 was toggling the LED. It seemed a bit odd to me, yet certainly within the realm of possibility, that the port numbering would be 0, 2, 3, instead of 0, 1, 2. So I just randomly tried a 01 in there and it works.
So now I have an external reset button attached to my board. It’s a bit twitchy. I might add a debounce timer in there to smooth that out a bit.
As a side note, I already knew this should be possible, because I had already implemented this feature on my re-spin of the tinyCylon using the 003, which also does not make the reset signal available on the smallest package, the -J4. The original tinyCylon is based on the 8 bit Atmel (now Microchip) AVR in an eight pin package. It used the external reset pin as a ‘mode advance’ input. Every time the button was pressed, it would advance the device mode. It was just easier to emulate an external reset pin in software than to re-architect the code.
I’m just a little disappointed that it wasn’t some sort of mystrious HardFault condition that would require Much Deep Thought. I’ve still got a nice HardFault reporting function planned. It is going to feature a much more advanced numeric output routine than I’ve previously used, and will be an excellent opportunity to try out an actual data algorithm (gasp).