ARM: Is there any way detect when write protected bit is written but locked? - Page 1
Forum section: electronics / general

author: frmdstryr
author_rank: Contributor
timestamp: May 12, 2023, 12:00:49 pm
content: I spent nearly all day debugging a USB device driver on a cortex-m4 yesterday that was not working.Was reading through the TRM with coffee this morning and saw one of the registers had a write protected bit so the write was being ignored and stupid thing was not enabling. Went and updated the code to unlock before the write and it works fine now...As the title states, is there any way to detect this?

author: ataradov
author_rank: Super Contributor
timestamp: May 12, 2023, 03:20:49 pm
content: ARM is an architecture. What specific device you are talking about? And what specific bit?

author: hans
author_rank: Super Contributor
timestamp: May 12, 2023, 03:41:32 pm
content: You could read back the register to see if the written value sticks.But it's a fix for an underlying issue. In this case, you should check if the peripheral is enabled before attempting a write.Also I want to emphasize to not confuse registers with RAM. Many registers may be implemented as D flipflops with a clock gate. However any signal, latch or flipflop could be muxed onto the data read bus when you the bus master (e.g. CPU) tries to access it.E.g. there are registers where you read 1s for e.g. interrupt status, and then need to write a 1 to clear them. The bit is then cleared to 0. These registers could be implemented with a series of SR or JK flipflops, where the hardware controls the 'set' lines, the write word connected to a 'reset' lines, and the read word is the output states of the flipflop.You could still check if the clear-1 write sticks, but in that case you'd need to check for zero (and also ensure that no other pending interrupt has occured)

author: frmdstryr
author_rank: Contributor
timestamp: May 12, 2023, 04:52:59 pm
content: It's a Nuvoton M482ZE8AE, and it was the USBROLE of the SYS_USBPHY.I see (now) that it says the bit is write protected in the docs, I was just using stuff from their example code so didn't look there... but the question was more if there is something for any cortex-m in general (eg like trigger a fault handler or something).

author: ataradov
author_rank: Super Contributor
timestamp: May 12, 2023, 05:16:56 pm
content: No, there is nothing general. It all depends on what specific vendor implemented in a specific peripheral.Reading back the written values is always a good idea, especially if something does not seem to work as expected.

author: wek
author_rank: Frequent Contributor
timestamp: May 12, 2023, 07:22:18 pm
content: > Reading back the written values is always a good idea, especially if something does not seem to work as expected.+1If something does not work as expected, my first step is to read out all relevant registers of all related peripherals and check against registers/bits/bitfields description in manual. The mcu does not work out of the source code nor "libraries" or clicky configurators, but it works out of the registers.My experience is, that "read out and check/post registers content" in the STM32 forum, in 50% of cases gets simply ignored, in 25% of cases results in "tell me how", in 15% of cases results in registers getting posted (often a screenshot and often in decimal) and in 10% of cases in "oh now I see what was the problem".JW

author: DavidAlfa
author_rank: Super Contributor
timestamp: May 12, 2023, 09:27:48 pm
content: It depends on the maker anyways.Some mcus call an exception if trying to modify a locked register, but the IRQ needs to be enabled in the NVIC in first place or you'll get nothing.Also you must consider and handle everything by yourself, it won't jump to a specific ISR just for the issue.For example, if trying to write locked config words, it'll will trrgger a Flash IRQ, but you must create that ISR beforehand, enable it, code all the stuff/registers parsing ... and determine what's going on.So yeah... it's much easier to simply read-back and verify the data.Hard fault would be a little excessive for such case, it's normally used for serious hardware problems.

author: amyk
author_rank: Super Contributor
timestamp: May 13, 2023, 12:09:45 am
content: Quote from: ataradov on May 12, 2023, 05:16:56 pmBut do check that the register is actually readable, and reading will read the same bits that were written.

author: ataradov
author_rank: Super Contributor
timestamp: May 13, 2023, 12:24:09 am
content: Quote from: amyk on May 13, 2023, 12:09:45 amThis is usually not a problem because when something does not match, you are forced to read the datasheet closely about the part that does not match. And hopefully this information is there.

author: cv007
author_rank: Frequent Contributor
timestamp: May 13, 2023, 07:54:01 pm
content: You could not have easily figured out that there were write protected registers in your mcu without either reading the ref manual (~170 mentions of the sys lock register) or understanding what your sample code was (originally) doing when it was using SYS_LockReg()/SYS_UnlockReg().QuoteYou have a bunch of registers (~60) that you know are write protected for your particular mcu (more unusual then normal), and your question seems to be how to handle dealing with this subset of registers.1. assume any register you write could be locked, so write, then read back to see if was locked, unlock/write/lock if neededno one would do this2. assume any register you write could be locked, so unlock/write/lock whether needed or notno one would do this3. understand which registers need unlock, save lock status, unlock, write, restore lock statussomewhat like globally disabling irq's, if some previous code unlocked and this is called code, the caller unlock state will be preserved4. understand which registers need unlock, unlock/write/lock registercannot have called code within that sequence that may also be doing the same thing5. unlock at start of app, lock when you decide all configuration is done or do not lock at allI would probably do this, no need to keep track of which registers are write protected, and if one decides to just leave lock protection off- well, 90% of theregisters are also not lock protected either3 & 4- if the registers had better names that would somehow indicate they are a write protected register (REG_wp), then they would become a usable option, but if you have to lookup each register you write to see if it is protected then it becomes too easy to get wrong (forgot to lookup)edit-5 could still be a problem if using sample code (any code) which locks/unlocks, since you could unknowingly end up in a locked state.

author: westfw
author_rank: Super Contributor
timestamp: May 14, 2023, 01:49:17 am
content: Presumably OP would like something similar to the "memory faults" that would occur if they accessed non-existent memory areas in the processor address space. AFAIK, individual vendor peripherals aren't going to have access to the ability to generate such a "fault" condition (faults are internal to the CPU core, and generally coverregionsrather than individual locations.) And it's unlikely that a vendor would "use up" on of the "external interrupt" vectors to provide a similar function (although ... it's an interesting idea - a CM4 does have "up to" 256 vectors to use.)

author: ataradov
author_rank: Super Contributor
timestamp: May 14, 2023, 02:13:08 am
content: Peripherals can't generate hard faults, but they can generate bus faults easily by simply setting corresponding flag in the response. Some Atmel MCUs do with synchronized registers where write would fault if synchronization from the previous write is still ongoing.But this is a stupid waste of logic resources, IMO. Just ignoring the write is good enough.

author: cv007
author_rank: Frequent Contributor
timestamp: May 14, 2023, 03:32:38 am
content: Actually I would do #5 as I stated earlier, but with a modification-Their sample code/drivers are full of SYS_UnlockReg()/SYS_LockReg(), and unless I was using all of their code as-is (am assuming all of their code unlocks when needed) I would comment out the body of the SYS_LockReg inline function and create a replacement with a similar name. Any other existing code can then unlock as it wants but will not lock (empty inline function). If you want to lock, then only you know the name of the function and no one else will be able to lock, although I tend to think the lock is not necessary.You could then unlock at the start of the app and would never get into a position where other code put the registers back to a locked state. No need to keep track of which 60+ specific registers are write protected or worry about other code locking these registers. If you do want to eventually lock again, other code out of your control will still be able to unlock so would keep working.The ref manual states 'Some of the system control registers need to be protected to avoid inadvertent write and disturb the chip operation', so it seems they tend to think programmers using their mcu will be writing to (specific) unintended destinations. That is not an easy thing to pull off even for a bad programmer, and if it does happen I would think it would be better to have some side effect. A write to anywhere not intended is a problem, write-protected or not, and the sooner you notice a problem the sooner it gets fixed.

author: ataradov
author_rank: Super Contributor
timestamp: May 14, 2023, 04:10:43 am
content: A general issue with all those rando protections for some bits is that authors can't explain what they are protecting against, so implementations end up being useless.There are multiple scenarios where accidental writes may happen. First of all, runaway code execution. But this specific implementation does not really do anything against it. If the software patterns would be unlock/write/lock, then it might as well runaway just before the unlock. Plus it is likely to mess things up that USB configuration does not really matter anymore.Another scenario is incorrect memory writes (poor bounds checking, incorrect DMA configuration). This lock would protect against that, but it still would not help, since this type of write would overwrite all other surrounding registers that can't be protected. So, overall, the system is still screwed.The only time protections are reasonable is on the components that are essential to system recovery (WDT, may be clock system). And in that case it makes sense to use a password as part of the register write, and may be even a sequence of passwords before changes are accepted. And as an additional layer make those write-once, so that POR is required to make changes.As far as random locks go, I personally just unlock all the registers that are locked by default in the initialization for a specific peripheral and never lock them back.

author: cv007
author_rank: Frequent Contributor
timestamp: May 14, 2023, 09:11:29 am
content: QuoteThe avr0/1 series has a little bit of that, such as setting a lock bit on the clock control which prevents any further clock changes until a reset (any reset). Makes more sense, but you still cannot get this mcu to switch from a clock source to one that does not exist (like ext clock, but there is no ext clock), so if you are inadvertently change the clock source or prescale you will still always end up with a clock and the only thing you really gained was hiding a problem that should be visible (or you have code that is intentionally changing the clock when it should not be doing so, so are now hiding the fact your code is kind of broken since some part of it is not getting what it wanted, and is most likely not checking if it actually changed the clock).They also have fuses, such as the wdt fuse register which if not 0 will lock the wdt period values from the fuse value and cannot be changed at runtime. This is one of the few that makes sense.The register configuration protection used on some of the avr0/1 registers (spm/io) is also a little bit like the Nuvoton being discussed- if you somehow inadvertently end up by these particular register writes odds are pretty good you also end up doing the unlock also.Some of the mcu design decisions made in this area must not be fully thought out and simply becomes a bit of a pain for the mcu user with little to no benefit.

author: Siwastaja
author_rank: Super Contributor
timestamp: May 14, 2023, 01:01:11 pm
content: Quote from: ataradov on May 14, 2023, 04:10:43 amYes. Many of these "locks" are total cargo cult engineering from the MCU manufacturer, and as usual for cargo cult, actually come with more downsides than upsides: increase in chip size, longer documentation to maintain, longer documentation to read, larger code size, more surface area for bugs that prevent the thing from working, and usually not any kind (or very little) of improvement in safety/security.