1. 源由

作为后续研读Ardupilot的ChibiOS的垫脚石,先了解下ChibiOS系统。


Ardupilot ChibiOS项目: https://github.com/ArduPilot/ChibiOS

Artery(AT32) porting项目: //Artery官网没有相关porting动作,不过开源github有相关项目。

2. ChibiOS基础知识4/5

2.13 Chapter 13 - RT Synchronous Messages

2.13.1 Basic concepts

  • Synchronous Messages are a unique feature of ChibiOS/RT that allows to create client/server architectures into an embedded system. RT implements in its inner scheduler layer a message-passing mechanism, when a context switch is performed a message is always passed between the thread being switched out and the one being switched in. The message is exchanged with almost no overhead. This inner mechanism is used to implement the Synchronous Messages high level functionality.

  • Client and Servers, When using synchronous messages there are two kind of threads: clients and servers.

Clients are threads that start a transaction by sending a message to a server thread then wait for a response message.

Servers are threads that wait for a transaction start from a client, once a message is received the server processes it and finally send a response message to the client. Servers are able to handle one message at time but can also handle multiple messages from different clients and to returns answers in an arbitrary order.

在这里插入图片描述

  • Messages are always signed scalars with type msg_t. This type is guaranteed to be cast-able to/from data pointers. Clients can send simple encoded messages but also pointers to structures representing complex transactions.

There are three predefined messages used internally to the RT kernel:

  1. MSG_OK. Defined as 0 is a generic acknowledge message.
  2. MSG_TIMEOUT. Defined as -1 is the message sent in case of timeouts.
  3. MSG_RESET. Defined as -2 is the message sent to inform of an object reset condition.

Note: It is assumed that pointers with values 0, -1 and -2 to not be valid pointers. Also note that there are no dedicated objects involved, the exchange is done directly between threads, each thread has its own queue of incoming messages.

  • Message Passing, In this scenario there are multiple threads in the system that never share data, everything is done by exchanging messages. Each thread represents a service, the other threads can request the service by sending a message.

在这里插入图片描述

2.13.2 APIs

Function NameDescription
chMsgSend()Sends a message to the specified thread.
chMsgWait()Waits for a message and returns a pointer to the sender thread.
chMsgGet()Retrieves the message after exiting from chMsgWait().
chMsgRelease()Returns an answer to the specified sender and releases it.
chMsgIsPendingI()Evaluates to true if there is a message waiting in the queue.

2.14 Chapter 14 - RT Events

2.14.1 Basic concepts

2.14.1.1 Events
  • Event Sources are the objects that broadcast events to system.
  • Event Flags, Events also carry information, the information is encoded as Event Flags, a mask of flags of type eventflags_t are broadcasted by sources together with the event itself.
  • Event Listeners, On each event source one or more event listeners can be registered, each event listener is linked to a single thread.
  • Events Masks, A set of pending events at thread level is called an Events Mask and has type eventmask_t, this type has must not be confused with event flags.
2.14.1.2 Operations
  • Registering
    The register operation is performed by a thread in order to become a listener of an event source, the association is mediated by an event listener object as follow:
PROCEDURE register(source, listener, events, wflags)
  LET listener.flags = 0
  LET listener.wflags = wflags
  LET listener.events = events
  LET listener.thread = current_thread
  source.listeners = source.listeners + listener
END
  • Waiting for Events
    The wait operation allows a thread to check for pending events or wait for them if none:
FUNCTION wait(events)
  LET current_thread.ewmask = events
  IF current_thread.epending AND current_thread.ewmask = 0
    WAIT
  END
  RETURN current_thread.epending AND current_thread.ewmask
END
  • Broadcasting
    The broadcast operation notifies all the registered threads that an event occurred on an Event Source, it is quite complex:
PROCEDURE broadcast(source, flags)
  FOR EACH source.listeners AS listener
    LET listener.flags = listener.flags OR flags
    IF (listener.flags AND listener.wflags) <> 0
      LET listener.thread.epending = listener.thread.epending OR listener.events
      IF listener.thread.epending AND listener.thread.ewmask <> 0
        WAKEUP listener.thread
      END
    END
  END
END
  • Simplified Events
    There is also another way to use events without recurring to event sources and listeners. A thread can directly signal another thread. In this scenario there is no decoupling between sources and threads, specific threads or ISRs signal specific threads with a mask of event flags. The targeted object is directly the thread handling the event.
PROCEDURE signal(thread, events)
  LET thread.epending = thread.epending OR events
  IF thread.epending AND thread.ewmask <> 0
    WAKEUP thread
  END
END

2.14.2 APIs

Function NameDescription
EVENTSOURCE_DECL()Event sources static initializer
EVENT_MASK()Translates from an event identifier to an event mask
chEvtObjectInit()Initializes an event source object of type event_source_t
chEvtRegister()Registers the current thread on an event source by assigning it an event identifier
chEvtRegisterMask()Registers the current thread on an event source by assigning it a mask of events
chEvtRegisterMaskWithFlags()Registers the current thread on an event source by assigning it a mask of events and a set of flags
chEvtUnregister()Unregisters the current thread from an event source
chEvtGetAndClearEvents()Returns the events pending for the current thread
chEvtAddEvents()Adds a mask of events to the current thread
chEvtSignal()Adds a mask of events to the specified thread
chEvtSignalI()Adds a mask of events to the specified thread (I-Class variant)
chEvtBroadcast()Performs the broadcast operation on an event source with no flags
chEvtBroadcastI()Performs the broadcast operation on an event source with no flags (I-Class variant)
chEvtBroadcastFlags()Performs the broadcast operation on an event source and adds the specified flags to event listeners
chEvtBroadcastFlagsI()Performs the broadcast operation on an event source and adds the specified flags to event listeners (I-Class variant)
chEvtGetAndClearFlags()Returns the event flags pending in the specified event listener
chEvtGetAndClearFlagsI()Returns the event flags pending in the specified event listener (I-Class variant)
chEvtWaitOne()Waits for exactly one of the specified events
chEvtWaitAny()Waits for any of the specified events
chEvtWaitAll()Waits for all the specified events
chEvtWaitOneTimeout()Waits for exactly one of the specified events with timeout
chEvtWaitAnyTimeout()Waits for any of the specified events with timeout
chEvtWaitAllTimeout()Waits for all the specified events with timeout
chEvtIsListeningI()Verifies if there is at least one listener registered on the event source (I-Class variant)
chEvtDispatch()Calls the functions associated with an events mask

2.15 Chapter 15 - RT Debug

ChibiOS/RT provides a comprehensive set of debug options meant to assist the developer during the system implementation and debug phase. All the debug options are reachable into the kernel configuration file chconf.h, each project has its own copy of this file.

2.15.1 Compile Time Checks

Configuration errors are, by design, detected at compile time, the system headers include logic checks that result in compilation errors in case of a wrong configuration.

2.15.2 Runtime Checks

Most debug options operate at runtime in order to catch design or programming errors. If a problem is detected then the system is stopped into the function chSysHalt() and the global variable ch.dbg_panic_msg points to an error message string.

2.15.3 Kernel Statistics

The debug option CH_DBG_STATISTICS enables support for kernel statistics. Statistics include:

  • Number of served IRQs.
  • Number of context switches.
  • Time measurement of thread-level critical sections: best, worst, last cases are stored.
  • Time measurement of ISR-level critical sections: best, worst, last cases are stored.
  • For each thread the following counters are kept:
  1. Longest execution time.
  2. Shortest execution time.
  3. Last execution time.
  4. Cumulative execution time.

Times are measured using the realtime counter and are clock cycle accurate. The ChibiOS/RT Eclipse plugin is able to show the runtime statistics of the application under debug.

2.15.4 System State Checks

The debug option CH_DBG_SYSTEM_STATE_CHECK enables an unique ChibiOS/RT, the System State Checker. This option is able to detect any call protocol violation, calling OS APIs out of the proper context is one of the greatest sources of hard to detect problems and random crashes.

2.15.5 Functions Parameters Checks

The debug option CH_DBG_ENABLE_CHECKS enables the parameters checks at API level. This option is able to detect application errors causing the application to pass invalid parameters to the RTOS, a typical example are NULL pointers passed where a reference to a valid object is expected. It is advisable to keep this option enabled through the whole development process. Safety concerns may require to keep this kind of checks in place also in the final code as a defensive measure.

2.15.6 System Assertions

The debug option CH_DBG_ENABLE_ASSERTS enables system-wide integrity checks on the RTOS data structures. The system is also checked for unexpected runtime situations. It is advisable to keep this option enabled through the whole development process. Safety concerns may require to keep this kind of checks in place also in the final code as a defensive measure.

2.15.7 Trace Buffer

The option CH_DBG_TRACE_MASK is an “or” of various option flags, each option selects an event to be traced:

  • CH_DBG_TRACE_MASK_NONE. No events traced by default (but tracing can be activated at runtime for any event).
  • CH_DBG_TRACE_MASK_SWITCH. Context switches are traced by default.
  • CH_DBG_TRACE_MASK_ISR. ISR enter and leave events are traced by default.
  • CH_DBG_TRACE_MASK_HALT. The halt event is traced, of course it is the last event recorded.
  • CH_DBG_TRACE_MASK_USER. User events are recorded. Application code can trace events using the chDbgWriteTrace() API.
  • CH_DBG_TRACE_MASK_SLOW. All events are enabled except IRQ-related ones.
  • CH_DBG_TRACE_MASK_ALL. All events are enabled.
  • CH_DBG_TRACE_MASK_DISABLED. The trace subsystem is removed entirely from the OS image.

The trace buffer stores the last N context switch operations. It can be used to determine the sequence of operations that lead to an halt condition. The option CH_DBG_TRACE_BUFFER_SIZE allows to change the size of the trace buffer, the default is 128 entries.

2.15.8 Stack Overflow Checks

The debug option CH_DBG_ENABLE_STACK_CHECK enables checks on stack overflow conditions. The implementation of the detection is port-dependent and can be implemented differently in each port or even be not supported at all. The most common implementation is to check the stack position when a context switch is about to be performed, if the calculated new stack position overflows the stack limit then the system is halted. Safety concerns may require to keep this kind of checks in place also in the final code as a defensive measure.

2.15.9 Working Area Fill

The debug option CH_DBG_FILL_THREADS fills the threads working area with a fixed 0x55 pattern before the thread is executed, this allows to calculate the effective stack usage by the various threads. The ChibiOS/RT Eclipse plugin is able to calculate the unused stack size for each thread if this option is enabled. Optimizations of the unused stacks should only be performed:

  • At development end.
  • With all other debug options disabled or in their final settings.
  • Using the final compiler version.
  • Using the final compiler options.

Use case in optimizing stacks because different compiler options or compiler version can change stack sizes dramatically and there is the risk of introducing errors not easily detected in the final code (with checks disabled).

2.15.10 Threads Profiling

The debug option CH_DBG_THREADS_PROFILING enables a system tick counter in each thread, after a long execution time relative values of the counters indicate the relative “weight” of all threads. This option has been superseded by CH_DBG_STATISTICS and is not compatible with the tick-less mode.

3. 参考资料

【1】ArduPilot开源飞控系统之简单介绍
【2】Ardupilot开源飞控之ChibiOS简介
【3】 ChibiOS官方文档

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐