User Tools

Site Tools


wiki:camkesoverview

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

wiki:camkesoverview [2018/05/08 19:30] (current)
Line 1: Line 1:
 +====== CAmkES ======
 +
 +CAmkES is an acronym that stands for “Componentized Architecture for microkernel based Embedded Systems”. Within the architecture that CAmkES provides, is an architecture description language (ADL), a code generation tool, and a run time for the generated code. The ADL portion helps to set up seL4 mechanisms and abstract their usage away into a more natural usage. Basically, everything in the [[wiki:​initialuserspace|Initial Userspace Deep Dive]] section is taken care of for you.
 +
 +===== Work flow =====
 +
 +  * Pull in the capdl loader application
 +  * Create your application directory. It should have the following files
 +    * ''​%%Kbuild%%''​
 +    * ''​%%Kconfig%%''​
 +    * ''​%%Makefile%%''​
 +    * ''​%%README.md%%''​ (optional)
 +    * ''​%%components/​%%''​
 +    * ''​%%include/​%%''​
 +    * ''​%%interfaces/​%%''​
 +    * ''​%%<​app-name>​.camkes%%''​ (top level camkes file)
 +
 +==== Kbuild ====
 +
 +This file requires the following lines
 +
 +<​code>​
 +apps-$(CONFIG_APP_<​APP-NAME>​) += <​app-name>​
 +<​app-name>:​ <library list>
 +</​code>​
 +Here, the app name is defined in the ''​%%$CONFIG%%''​ variable and should be all caps, while the ''​%%<​app-name>​%%''​ can be lower case. It is **IMPORTANT** to make sure all references to ''​%%<​app-name>​%%''​ are spelled the same way. The ''​%%<​library-list>​%%''​ is the list of libraries that your app will need. It is generally okay to grab a list from one of the solutions in the tutorials to start with. Something like ''​%%libsel4 libmuslc libsel4platsupport libsel4muslccamkes libsel4camkes libsel4sync libsel4debug%%''​ should be okay. If you want to use the benchmarking features, add ''​%%libsel4bench%%''​ to the list.
 +
 +==== Kconfig ====
 +
 +This file determines how your options will appear when ''​%%make menuconfig%%''​ is run from the root of the project. The general layout would be similar to:
 +
 +<​code>​
 +config APP_<​APP_NAME>​
 +    bool "The app description"​
 +    default n
 +    help
 +        Some help text here
 +</​code>​
 +It is important to make sure the ''​%%<​APP_NAME>​%%''​ in this file and ''​%%Kbuild%%''​ are the same.
 +
 +==== Makefile ====
 +
 +This is what is pulled in by the top-level ''​%%Makefile%%''​ in the root of the project. A general template would be similar to:
 +
 +<​code>​
 +TARGETS := $(notdir ${SOURCE_DIR}).cdl
 +ADL := <​app-name>​.camkes
 +
 +<​component>​_CFILES := \
 +    $(patsubst ${SOURCE_DIR}/​%,​%,​$(wildcard ${SOURCE_DIR}/​components/<​component>/​src/​*.c))
 +<​component>​_HFILES := \
 +    $(patsubst ${SOURCE_DIR}/​%,​%,​$(wildcard ${SOURCE_DIR}/​include/​*.h))
 +
 +include ${PWD}/​tools/​camkes/​camkes.mk
 +</​code>​
 +It is important to make sure the ''​%%$ADL%%''​ variable is set to your top-level camkes file and that you have make rules for all of the components in your project.
 +
 +==== README.md (optional) ====
 +
 +The ''​%%README.md%%''​ is optional but your team-mates and future self may thank you for some top-level documentation.
 +
 +==== $APP-NAME.camkes (top level camkes file) ====
 +
 +This is your top level camkes file. It generally imports the other components and links everything together inside an ''​%%assembly%%''​ block. Within the ''​%%assembly%%''​ block there is generally a ''​%%composition%%''​ block and a ''​%%configuration%%''​ block. The ''​%%composition%%''​ block instantiates components and connects their data ports or other connectors. The ''​%%configuration%%''​ block sets access to objects or other component attributes. In this simple templated example, two components of the same type are instantiated,​ they are connected via a ''​%%seL4SharedData%%''​ connection, and port access is set to make the connection one way.
 +
 +<​code>​
 +import <​std_connector.camkes>;​
 +
 +import "​components/<​component>/<​component>​.camkes";​
 +
 +assembly {
 +    composition {
 +        component <​component>​ <​component-instance-1>;​
 +        component <​component>​ <​component-instance-2>;​
 +
 +        connection seL4SharedData shared_data(from <​component-instance-1>​.port,​ <​component-instance-2>​.port);​
 +    }
 +    configuration {
 +
 +        <​component-instance-1>​.port_access = "​R";​
 +        <​component-instance-2>​.port_access = "​W";​
 +    }
 +}
 +</​code>​
 +This is not an exhaustive template. For more CAmkES information consult the [[https://​github.com/​seL4/​camkes-tool/​blob/​master/​docs/​index.md|manual]]
 +
 +==== components/ ====
 +
 +Within the ''​%%components%%''​ directory there is a directory for each component definition. The directory layout would be similar to:
 +
 +<​code>​
 +components/
 +└── <​component-name>​
 +    ├── <​component-name>​.camkes
 +    └── src
 +        ├── <​component-src-file-1>​.c
 + ​   ​    ​└── <​component-src-file-2>​.c
 +</​code>​
 +The component definition in the ''​%%<​component-name>​.camkes%%''​ CAmkES file can be used in other files, like the top-level CAmkES file, to create instances of it and connect to other component instances.
 +
 +An important CAmkES keyword is the ''​%%control%%''​ keyword. If this is included in a component’s definition, then that component will be considered “active” and the source code needs to include a ''​%%run%%''​ function. Inactive components, such as handlers and communication channels, run in a thread which loop and check for notifications that trigger user defined functions. A template for a simple ''​%%component%%''​ definition would be similar to:
 +
 +<​code>​
 +import "​../​../​interfaces/<​an-interface>​.camkes";​
 +
 +component <​component-name>​ {
 +  include <​some-header>​.h
 +  control;
 +  uses <​interface>​ <​interface-instance>;​
 +  dataport Buf port; // This was used in the top level camkes file
 +}
 +</​code>​
 +This component is an active component that is using an interface defined in an external CAmkES file and has a dataport to communicate with another component.
 +
 +A source file for this component might look similar to:
 +
 +<code c>
 +#include <​stdio.h>​
 +#include <​camkes.h>​
 +#include <​camkes/​dataport.h>​
 +
 +int run (void) {
 +  printf("​I can print from here!\n"​);​
 +
 +  // Copy to a dataport
 +  int *n = (int*)port;
 +  char *str = (char*)(port + 1);
 +  strcpy(str, "​hello"​);​
 +
 +  return 0;
 +}
 +
 +</​code>​
 +It is important to include the ''​%%camkes.h%%''​ since it is a generated header for this component. The CAmkES header files include the prototypes for the dataports and attributes that were defined for the component in the CAmkES files, so they are globals here. Another component’s source file won’t have the same CAmkES header file as this one, since they are generated and placed in the correct places during build time.
 +
 +You can see the structure for the ''​%%Buf%%''​ CAmkES type in ''​%%libsel4camkes/​include/​camkes/​dataport.h%%''​.
 +
 +<code c>
 +/** \brief A convenience type for CAmkES dataports.
 + *
 + * The default dataport type in CAmkES is `Buf`, a generic type for a
 + * page-sized shared memory region. While the user is provided with a typed
 + * pointer, this should never be directly dereferenced. The only legal things
 + * to do with a `Buf` are to call `sizeof` or cast a pointer to one to a
 + * pointer of another type. E.g.
 + *
 + ​* ​    char my_buffer[sizeof(Buf)];​
 + ​* ​    ​strncpy(my_char,​ buf_ptr, sizeof(Buf));​
 + */
 +typedef struct Buf_ {
 +    char content[PAGE_SIZE_4K] DEPRECATED("​Buf type incorrectly accessed directly"​);​
 +} Buf;
 +</​code>​
 +The CAmkES dataports expand from ''​%%jinja%%''​ templates and can be seen in ''​%%tools/​camkes/​camkes/​templates/​seL4SharedData-common.template.c%%''​.
 +
 +==== include/ ====
 +
 +This directory contains header files that might define structures that can be used in the component CAmkES definition and source files similar to how the ''​%%Buf%%''​ structure was used.
 +
 +==== interfaces/ ====
 +
 +The interfaces directory contains other CAmkES building blocks for the other components in your application. These are commonly ''​%%procedures%%''​ blocks. A CAmkES component would generally ''​%%import%%''​ the CAmkES files in this directory.
 +
 +A general procedure block would look similar to:
 +
 +<​code>​
 +procedure <​interface-name>​ {
 +  <​return-type>​ <​function-name>​ (<​argument-direction>​ <​argument-type>​ <​argument-name>​);​
 +}
 +</​code>​
 +A CAmkES component needs to provide the interface for it to be used by another component:
 +
 +<​code>​
 +component <​provider-component-name>​ {
 +  provides <​interface-name>​ <​interface-instance-name>;​
 +}
 +</​code>​
 +A CAmkES component can then use this interface similar to:
 +
 +<​code>​
 +component <​user-component-name>​{
 +  uses <​interface-name>​ <​interface-instance-name>;​
 +}
 +</​code>​
 +These two components need to be connected via a CAmkES provided connection. This is usually done in the top level CAmkES ''​%%configuration%%''​ block.
 +
 +<​code>​
 +configuration {
 +  <​provider-component-name>​ <​provider-instance>;​
 +  <​user-component-name>​ <​user-instance>;​
 +  connection <​connection-type>​ <​connection-instance>​(from <​user-instance>​.<​interface-instance-name>,​ to <​provider-instance>​.<​interface-instance-name>​);​
 +}
 +</​code>​
 +In the source of the procedure provider CAmkES component the functions would be implemented similar to:
 +
 +<code c>
 +<​return-type>​ <​interface-instance-name>​_<​function-name>​(const <​type-argument-mapping>​ <​argument-name>​)
 +{
 +    // Implementation
 +}
 +</​code>​
 +It is important to realize that the ''​%%<​interface-instance-name>​%%''​ is in relation to the component that it is associated with. The interface provider can also define a interface initialization function if its function signature is ''​%%void <​interface-instance-name>​__init(void)%%''​.
 +
 +The component that uses this procedure can make calls to the interface similar to:
 +
 +<​code>​
 +
 +int run(void)
 +{
 +  <​interface-instance-name>​_<​function_name>​();​
 +}
 +</​code>​
 +A possible usage would be to run utility functions such as printing over an RPC CAmkES connection. More can be found in the CAmkES manual.
 +
 +===== Parsing Process =====
 +
 +The CAmkES parsing process generally goes as follows:
 +
 +  * Parses the CAmkES description file
 +  * Fills in and expands templated code
 +  * Uses the CapDL python tool to create the CapDL spec that the CAmkES project needs
 +
 +If you would like to see more output while running ''​%%make%%''​ from the root of your project, set the verbosity level by setting the ''​%%V%%''​ environment variable and save to a text file for easier viewing:
 +
 +<​code>​
 +V=3 make | tee makeoutput.txt
 +</​code>​
 +====== CapDL ======
 +
 +The developer does not really have to worry about the finer points of CapDL but they should be aware of what it is and how it fits into the build system.
 +
 +  * Capability Description Language
 +  * A Data61 language used to take a description of capabiltiies and create the glue code and set up code to implement these capabilities
 +  * The tool also provides the ''​%%capdl-loader-app%%''​
 +    * This runs as the initial root thread that the seL4 kernel first drops down to
 +  * Examples can be found in ''​%%capdl/​capDL-tool/​example.cdl%%''​.
 +  * The CapDL spec for your project should show up in ''​%%build/​$ARCH/​$PLAT/​$APP-NAME/​$APP-NAME.cdl%%''​
 +  * The CapDL usage is largely hidden from the user. The only necessary interaction is to select the ''​%%capdl-loader-app%%''​ in the ''​%%menuconfig%%''​ Applications list.
 +
  
wiki/camkesoverview.txt · Last modified: 2018/05/08 19:30 (external edit)