- Feature Articles
- CodeSOD
- Error'd
-
Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
As the song goes:
"Walking back to cr@ppiness ..."
Admin
If the PWM generators are programme to make an audible frequency, maybe, hooking a loudspeaker on the pin it's possible to hear the program working and if a test is failing or not....
Admin
Using PWM? I don't like the sound of that.
Admin
Deliberately taking the piss?
I knew someone who built a Rugby clock using, I think, a Z80, with no RAM, because it had enough registers.
But it only just had enough registers - this did involve using the upper few bits of the dynamic RAM refresh control register (the bottom few bits weren't any use because they changed too fast).
Admin
What are you testing exactly? First off, it's utterly ridiculous to test on-chip RAM (OCM). If you are testing all of OCM then you just trashed your stack. That's TRWTF. You test external memory. You run your code in OCM, or perhaps XIP in FLASH memory, and you use the OCM RAM for stack and variables.
Admin
Including the shadow registers?
Admin
It is using the PWM registers as a small RAM to provide workspace for internal variables, so it can test ALL of the on-chip RAM. Code is being run from ROM : this code was almost certainly not called as a subroutine, but in-line at initialisation.
If the RAM passes the test, then you can continue running code using the RAM. Otherwise the MCU is dead.
The only strangeness in fact is setting a flag saying the RAM is good at the end of the test. Either it is good and you continue, or it fails and you stop, and do something to alert the outside world.
All it needs is that as an explanation of the choice made, not that it is a bad choice...
Admin
Are we sure these really are PWM registers? The declarations at the beginning of the code block look like they're just calling them PWM registers, but actually map to the bottom of the regular RAM. (Now of course that address space could indeed be mapped to a physical device, but without any comments, things are difficult when working with low-level hardware access)
Admin
I don't know nearly enough about chip architecture to judge whether using PWM registers makes any sense, but plenty of other things in that code strike me as WTFs - the use of 30 to mean "failure detected" for a start. Why 30?
Admin
There are additional weird things in that code.
Take PWMDTY4 for example. It serves as a loop counter and index to access values in that _PowOfTwo_16 array. Yet it some places it is arbitrarily set to 30 (magic number!) just to trigger various if/else branches (from the looks of it, the value 30 means "The test has failed"). That's a dangerous mix of concerns, especially when dealing with low-level memory access. If the dev had messed up and accidentally accessed PowOfTwo[30], it could have returned something from garbage memory and caused undefined behaviour. Also, the value of PWMDTY4 might even be overwritten by various iterations of some loop, so it's not even guaranteed that it properly works.
Instead of setting PWMDTY4 to 30 in the middle of a loop and happily resuming the loops, they should just have used some goto statement to exit the loops and go straight to the code saying the test was failed.
There's also a suspicious smell in those ((uint16_t)PWMDTY01 casts. Maybe they are actually necessary for that memory test. And maybe there's some bad typing lurking in the shadows and this is an ugly workaround. In any case, here be dragons.
Admin
Agreed with the others, o obvious WTF in the design. Using the PWM registers rather than general purpose is potentially a GOOD idea. There is always the possibility that the compiler will decide to use a given register and cause problems, by avoiding the common registers this problem it mitigated.
Admin
C'mon, it was a long time ago, and I never saw the code - I'm just reporting what the guy who built it told me. At a clock changing party, where we were watching it switch from 3am back to 2am (or whatever it was). If I ever knew any more detail I've forgotten it.
Admin
If the PWM register outputs are enabled before the test, it should produce some interesting results during EMI testing. Probably too fast for a LED show, but it might make a distinctive sound if amplified, whether intentionally or not. Some MCU programs leak data that way, as audible signals in their power supply coils.
Admin
TRWTF is using C for something that should have been done in assembly language.
Admin
Wow what a bad piece of crt0 code, normally you would do this as part of initialisation before main() in the standard crt0 module suitable for the environment in the EABI version (bare metal no OS) of compiler. This has to be before the Flash to RAM copy of initialised variables in RAM.
So we take the block of RAM which could be kB or MB, write a pattern ONCE, so far reasonable, then READ the SAME pattern up to 16 times if you are expecting changes between read passes you are doing something else wrong.
However when we read the SAME pattern from the same starting point but set the starting comparison value with
So unless that is a MACRO to actually set the starting pattern to the SAME starting value, every subsequent pass will fail. This will only work with a table of 16 IDENTICAL values.
Using PWM registers is a VERY BAD idea, on nearly all micros various parts of the micro are on DIFFERENT busses, often Flash and RAM are on slightly different busses as Flash is slower than most RAM these days, and RAM is often Pseudo Static RAM with automatic referesh control, let alone Flash and RAM could be cached whilst peripherals are NOT. Think of this like the North Bridge and South Bridge controllers on PCs. There are many steps on many peripherals to power up, enable them and set which clock they have on most of the new ARM processors for the last 15 years.
Having written various crt0 modules for various micros over the years, this is bloated and pointless, often written in assembler using only general registers, before copying .init section to its place in RAM, THEN setting up the stack.
Admin
Firstly, this sort of thing should be written in assembly so you can be sure exactly what is happening (and if you don't know assembly well enough, you have no business doing such a low-level task - e.g. have you set up any caches correctly?).
And secondly, there's an off-by-one bug which may make it write off the end of the RAM area. If a failure is detected, it assigns RAM_END to PWMDTY01 without using break or goto. At the end of that loop it them uses that as an address to write PWMDTY23 to, but RAM_END is clearly the first address not in RAM as the tests against it are less-than rather than less-than-or-equal.
In the absence of context that suggests otherwise, it seems that ramTestPassed is an ordinary variable, so presumably stored in RAM. The RAM which might have just failed, so it's pretty stupid to store something valuable there.
Admin
Possibly this: https://en.wikipedia.org/wiki/-30-
Admin
Since these registers are usually used to control sound generation (maybe for a modem), I can just imagine what this would sound like if the speaker is hooked up.