Atomthreads, active ojects

Atomthreads and active object design pattern

Atomthreads is a small task scheduler with AVR, stm8 and stm32 ports available. It has the very permissive BSD licence. More about it’s features here.

It’s a preemptive scheduler with multiple priorities for threads, and it provides expected rtos features like message queues, mutexes, semaphores, timers. This post will have a buildable example project for Atmega1280/328 to get started with it(soon). (and is also intended as notes for self).

Atomthreads is very lightweight, the core is written in ANSI C, and only a very small amount of architechture specific code is required. Atomthreads uses only a single timer in it’s avr port for it’s system tick.

Multithreading considerations

Some things to take care of when programming with an rtos/task scheduler such as atomthreads, chibios, freertos(list of other open source RTOSs):

  • ‘Threads’ cannot/should not hold CPU captive by things like continuous polling for something which might take time, like waiting for an interrupt to change the value on some flag variable.

  • Functions(at least those that are common between threads) should be reentrant. Usually this means using only stack for variables, so no static or file scope/global variables. Shared resources might need control mechanisms like mutexes. More on reentrant code later.

  • Care should be taken to avoid priority inversion, which usually happens when a shared resource is involved, more on this later.

  • All interrupt handlers apart from the system tick interrupt which you setup at the start should be enclosed in AtomIntEnter() and AtomIntExit(FALSE), this prevents rescheduling. (There is usually something similar in other RTOSs too, check documentation).

About priority inversion:

Priority inversion happens when a medium priority thread preempts a lower priority thread while a higher priority thread is waiting on a shared resource currently with the lower priority thread. This means that even though the higher priority thread is ready to run (provided the lower priority thread finished it’s work and released control of the shared resource), the medium priority thread is executing in it’s place, i.e. an inversion of priority has occurred. This can lead to hard to find/reproduce bugs.

Reentrant code

Reentrant functions can have multiple concurrent invocations which do not interfere with each other, this is done by managing how the data is used in these. From here, I’ll just list the three conditions for reentrant code

  • It uses all shared variables in an atomic way, unless each is allocated to a specific instance of the function.

  • It does not call non-reentrant functions.

  • It does not use the hardware in a non-atomic way.

The first one an be taken care of in ways like not using any variables outsode of the scope of the function, using only local/auto (allocated on the stack) variables, using malloc for each instance to have it’s own data area(we don’t malloc in our embedded code though).

If using data, say a global variable, disable ISRs (only during the non-reentrant code parts), disabling ISRs means no context switching.

Another option is using mutexes, which are used to signal if a particular resource is in use. Atomthreads provide mutexes for our use, so do other RTOSs.

Rule 2 is obvious, if your code calls other non-reentrant code, then your code inherits the non-reentrancy.

Rule 3 can be taken care of in a similar way as when dealing with shared memory.

Active objects

One design pattern to prevent priority inversion (and other possible issues related to coding ‘naked threads’) is called the ‘active object’ pattern. In this, the thread and the resouces it needs are encapsulated together, and the resources are not exposed by any interface. The threads act like message routers. An example of such an implementation would:

  • encapsulate the threads along with their resources

  • use thread safe message queues provided by the rtos to send and wait upon messages to perform an action

This allows for more efficient scheduling and prevents any deadlock(possibly) or priority inversion situation.

Notice that this means that for most things each thread need not even have reentrant code, since we encapsulate all the resources a thread needs with itself and do not allow outside access

State machine design of threads

One good coding rule to follow while creating threads is to never wait for a particular message, instead accept and ‘route’ all messages, when the thread needs some kind of reply, make the other thread send a message to it’s queue. There might be an internal state to the thread which is affected by the incoming message, it can be implemented in a state machine, or even better as an hierarchical state machine, so all messages are still handled while waiting on a response even if a timeout). I’m still trying to figure out how to implement such a hierarchical state machine myself.

Essentially, all threads should have exclusive access to their designated resources, and all that they should do is wait on their message queues to dispatch requests from other threads/ISRs/itself.

  • If the thread to which a message had been sent, wants to reply, the mechanism in this scheme would be to send a message on the caller’s message queue.
  • if a thread wants to signal itself, say of a timout or a successful operation, then it sends a message to it’s own queue and it is handled like any other message.
Posted on 29 Jun 2016

These are random notes I had about the topic of security in embedded systems

  • Why is it important
    • embedded devices are in places which are likely to be hidden from sight and work without as much intervention/interaction as other tech (desktop applications, websites)
    • we also have cars which are connected to the internet now(have remote firmware updates), also fridges, and TVs with mics and cameras
    • supposedly secure tech/service/device might be compromised due to underlying insecurity in an embedded device in the path
    • internet of things is the nightmare of pervasive embedded insecurity made real - Taylor swift
    • how important it should be to you would depend on how much is at stake (privacy, security of other systems dependant on this)
  • why is it hard
    • security is hard in general, for embedded systems it is even more harder
    • recent side channel attacks are really scary, and they seen to work to
      • that hardware on hackaday to fuzz click and datainput
    • cryptography is not the solution to all problems, software bugs(and maybe other stuff too) makes devices insecure
  • Cases in the wild
    • routers are regularly found to have big security issues, this can be really bass since routers are part of your infrastructure which other things use. See SOHOpelesdly broken
    • recently tp-link locked their firmware because of fcc change in rules regarding firmware which can be modified by customers
    • SCADA systems
    • lightbulb leaks wifi passwords
    • Chinese camera with built in p2p features communicates with dozens of ips despite the option to disable p2p on, on by default, vulnerable.
  • Common pitfalls
    • no encyption, or some obfuscation in name of encyption
    • using deprecated crypto, ex. WEP for WiFi, TLS versions which are no longer supported because of not being strong enough
    • common pitfalls of not sanitizing input
    • RNG issues, using sources with low entropy, predictable entropy, or sources which can be tricked (?)
      • esp8266 early firmware use constant seed for rng
    • insufficient key lengths in encryption
    • insecure hash functions,md5 no longer considered secure
    • firmware update issues
    • leaving private keys inside devices same across all devices (depends on how secure system needs to be)
  • Absolute basics of security
    • do not use homebrew crypto, it means don’t create own ways of authentication, or implement your own encryption cipher
    • use standard/public/peer reviewed cryptography, not proprietary/new/your own
    • do not use otherwise secure crypto libraries or functions in a non standard, non recommended way.
    • “A cryptosystem should be secure even if everything about the system, except the key, is public knowledge.”
    • obscurity does not add to security
  • Suggestions for the most common use cases
    • good coding practices to reduce the 3 most common errors resulting in bugs:buffer overflows, unchecked input, poor handling of integer type checks
      • always sanitize input
      • follow a coding standard maybe? MISRA-C
      • decouple, modules, reduce the amount of state the program has, minimize ‘globals’
      • famous apple bug, “goto fail; goto fail;”
      • properly use interrupts, should be short, modify minimal stuff
      • use fixed width integral types, uint8_t, uint32_t, int16_t etc. because int char long are allowed to be implementation defined by ISO C
    • rng
      • use hardware rng if available
      • of not use enough entropy. Example adc noise, use only LSB, xor with differences in click, LEB again, multiple readings, pass through some one way hash function recommended, etc.
    • OWASP is a really good resource for web application security guidelines, but security in writing software in general too. It had it’s problems though, it is not at all newbie friendly, the content is not very regulated, so good advice might be mixed in with bad advice.
      • they have an embedded security project that is really low in activity, maybe a new resource for general advice can be started
Posted on 01 May 2016