10. September 2021 · Categories: Software

Adding a lot of files, spread across multiple directories, to a SeggerStudio project is annoying, so I was looking for a faster way. Fortunately the project file is simple XML, so I can use unix tools to automate this a bit. The find tool is extremely powerful, and allow me to generate all the references in one go:

find .. \( -name *.c -o -name *.h \) -printf ' <file file_name="%p" />\n'

  • the group with the two -name patterns allows me to select all C header and source files. It must be grouped so that the printf applies to everything found.
  • the -printf then prints them out in exactly the form to paste them into the emProject file
26. April 2021 · Categories: Software

Sometimes it is very useful to attach a debugger to an already running target. With the STM32CubeIDE, the ability exists but is a bit convoluted to activate. This turns out to work:

  • start with your existing debug configuration, under Run|Debug Configurations…

  • Duplicate it and rename it to “Attach”

  • In Main, disable auto build

  • In Debugger, uncheck “Verify flash download”, and set the reset behavior to “None”.

  • In Startup, edit all the load images to no longer download

The option Debugger|Reset behaviour tells GDB what to do after it attaches:

  • Connect Under Reset will put the device in reset, then connect

  • Software System Reset will connect, then trigger a software reset

  • None will keep the device running

26. April 2021 · Categories: Software

freeRTOS has the ability to collect run time statistics when you activate the configuration configGENERATE_RUN_TIME_STATS. You still need to implement the timer yourself, though. On the Cortex-M processors, a pretty generic way is to use the system timer, so I adapted it to provide timing information with a 1µs resolution. Because freeRTOS uses 32bit numbers to store the counter, it will overflow after 70 minutes. For most performance checks that should be ample, but you can always change runTimeCountsPerSecond below to match your needs.

The code avoids costly divisions by first calculating the inverse, and scaling it with a shift to achieve a good compromise between speed and accuracy. This optimization is because the counter will be retrieved with every context switch, and so slightly distort the measurements.

Erich Styger shows a few alternatives. There I also learned that the tick counter must be atomic (portTICK_TYPE_IS_ATOMIC), which is always the case on Cortex-M, but could trip you on other CPUs.

26. April 2021 · Categories: Software

Typically, freeRTOS uses preemptive multitasking, which can lead you to needing to guard anything shared between the tasks. That is prone to mistakes, and thus I prefer to use cooperative multitasking instead.

There is an option, configUSE_TIME_SLICING, that can disable time slicing, but it only prevents the scheduler from interrupting the current task with another task of the same priority. The kernel still switches to another task of the same priority when a higher priority tasks interrupts, and then returns to another task. So the option does not provide protection from getting interrupted, it just removes some overhead. A better implementation would allow to set the number of ticks per time slice, in case you want high precision in the timers, but also avoid the overhead of very short slices.

We can provide correct cooperative multitasking in the following ways:

  • Timers: They all run in one task, but then a long task could block.

  • Event task: You have one central event queue, and the main program just processes these events. This is also recommended for timers, use the timer tasks to post to the event queue, and so prevent blocking from longer processing.

  • Global Mutex: a mutex protects the main data structures, and all tasks just take it when doing work. You then must yield regularly to allow the other tasks to proceed. That would be a sequence of xSemaphoreGive( xLock); vTaskDelay( 0); xSemaphoreTake( xLock, portMAX_DELAY);

To reduce time slicing, add an option configTICKS_PER_TIMESLICE that defaults to 1, and the following code to tasks.c. I modified version 10.4.3.

11. March 2021 · Categories: .NET

I recently was adding binding support to a custom WPF control in .NET, and was checking how you can integrate information from the bindings Binding.UpdateSourceTrigger setting. But you do not need to implement anything. If you just post an update on every change, the binding system itself will prevent the updates from being forwarded if you use a different mode than UpdateSourceTrigger.PropertyChanged. It might be useful to look at BindingOperations.GetBindingBase to retrieve the Binding, and determine when you need to post updates, but that is a performance optimization, not needed to get correct behavior.

20. February 2021 · Categories: Software

I recently had the problem to easily share files generated by Pythonista on iOS. The easiest way is to show the share sheet with the file afterwards, and this turns out to be trivial, once I figured out the logic.

The trick is that files can be shared as URLs, you just need to convert them first to an absolute path, and then to an URI so that the API understands them properly. Much more comfortable than searching for the generated file and then invoking the share sheet manually.

11. February 2019 · Categories: Software

I came across an interesting bug recently. Suddenly my firmware would start crashing, and in the debugger I see that it calls a function with wrong parameters. The offending code:

When the problem happens, var is actually 0. It turns out that the load of the variable address returned the value stored just before. On Arm, this is a PC relative load LDR R3, [PC, offset]. How can something so fundamental go wrong?

The behavior under the debugger is odd. When I single step through the code, there is no problem. I put a dynamic breakpoint after the load, triggering when a bad register value is detected. Still never triggered. I hit go, and just a few iterations later I hit the problem.

The code is executed just after the processor wakes from sleep, and the problem only happens after waking from deep sleep, but not from normal sleep. After deep sleep I need to switch from the default clock to my desired clock. The problem does not happen immediately, there are a dozens others instructions correctly executed after waking up before the read error occurs. What can cause this?

I use an STM32 processor, and run it using the HSI48 clock used for the USB peripheral. The processor has a clock recovery system (CRS) which can automatically trim HSI48 to be precisely 48 MHz. I have selected the internal RTC as the trimming reference. Now while the CPU is in deep sleep, all clocks apart from the RTC are stopped. When waking up, the CRS resumes counting once we are back on the HSI48. But the wakeup is caused be the same RTC, so the RTC clock events as seen by the CRS are systematically delayed, and so it decides to trim the HSI48 faster, and faster. In the end the processor is clocked just a tiny bit too fast for its internal flash memory, so reads go wrong.

To avoid this runaway, I updated the deep sleep code to reset the trim value after waking up:

So when your flash reads start to fail, remember to check the clocks. They might be trimmed outside specifications.

29. August 2016 · Categories: Software

There are two answers you get when you ask what characterizes an outstanding programmer:

Other Programmers: Knows programming languages into the smallest details, and can do amazing things with it where you pause and say: “This is possible?”

Normal People: Solves problems using software in such a way that it is now much easier and more enjoyable to deal with them.

This is a problem when you ask other programmers what you should be learning to become great. You need a good understanding of your tools so that you know what is possible, and which approaches are cost effective. But this is only the basis which you use to solve actual problems, and you need additional skills on top of pure programming to succeed:

Software Engineering On top of programming languages, you need to know about algorithms, to basically know how much various approaches cost and to have an idea how your solution will scale when used with more data. And of course the basics to keep your projects sufficiently organized, especially version control, but also project documentation, and some skills in estimation.

Domain Knowledge You need to learn enough about the problem so that you can understand what people are trying to achieve, what parts can be automated, and how you ensure that people will enjoy using your solution.

Communication Skills Most interesting problems can no longer be solved by a single person, you will have multiple people working on it, and you need to know how you can work effectively together.

Design Skills If your solution is not infrastructure plumbing, its success depends greatly on how easy and accurately it can be used by your customers. Most of design is not making it aesthetically pleasing, but providing an information flow and model that the user can work successfully with.

24. August 2016 · Categories: Software

With Vesper now shutting down, we lose a great app. It is ostensibly a notes taking app, but the excellent tagging system and the ease with which we can reorder entries manually makes it actually a free form task and thought organizer. It is this consequent replacement of folders with tags that makes it so powerful. It recognizes that folders are overkill until you are dealing with enough material to write a book.

One would have expected this to be widely copied, but sadly not. Unfortunately, the bar for a competitive notes app gets higher and higher every year, and with it the effort actually bring any innovative new idea successfully to market. Sadly it means that the chances of getting an adequate replacement for Vesper are slim unless one of the established apps decides to adopt this interaction model.