-
Notifications
You must be signed in to change notification settings - Fork 38
OVERVIEW
This section provides the architectural overview for mikroSDK (Software Development Kit). It describes each layer within the architecture and its associated modules.
The mikroSDK architecture consists of several key blocks listed below:
- Microcontroller HAL and peripheral drivers
- Application framework libraries
- Board definition with pin-mappings
- Component libraries
- User application code
This is the basic architecture block diagram of an mikroSDK platform:
Provides generic access to peripheral modules for upper layers and hides various MCU peripheral instantiation differences, so that the application can be abstracted from the low-level hardware details, enabling highly portable code.
Provides functions with hardware specific register access details.
The Drivers Handle provides API and implementation which allow you to interface with target microcontroller. This layer saves developers time since they no longer need to reinvent commonly used services and do not typically need to interface directly with the hardware. This enables shorter development cycles and rapid prototyping and code re-use on different microcontrollers.
Note : Use this layer to interface with microcontroller peripheral modules to ensure maximum portability, instead of HAL layer.
Middleware consists of sets of comprehensive libraries for common application development, such as graphics, communication stacks, file system, etc...
The Board Pin Mapping comes with the board.h
header file with all necessary pin mapping definitions.
It helps to develop portable applications for mikroBUS socket middleware libraries and other standardized modules witch comes on board or extension boards.
The Plugins libraries are for extension boards, such as Click boards, TFT boards, etc and they are separated from a mikroSDK project.
The User Application is where users implement logic for their application, using the services provided by the mikroSDK 2.0 framework.
Each module can define context structure for storing its state. The contents of the context structure are used by the module and must not be altered by user. Reading or writing data from a context structure should also be avoided as the data structure is not guaranteed to remain the same between mikroSDK releases. In general, context structures should be treated like black boxes. User of a module is responsible for static instancing, because dynamic memory allocation is not allowed.
The following code snippet shows an example of this:
uart_t uart;
uart.baud = 56000; // Not recommended
uart_set_baud(&uart, 56000); // OK
Using function to set field in context structure ensures encapsulation principles.
Example context structure for a Click driver module is shown below:
typedef struct
{
digital_out_t out;
spi_master_t spi;
int value;
} click_t;
In this example, click_t
context structure contains context structure for digital output (digital_out_t
), and context structure for SPI master driver (spi_master_t
). It also can contains other fields for storing module instance data.
Naming convention for context structures is <module_name>_t
.
Each module can provide configuration structure which are used for configuring a module's initial state.
Usually, it contains pin names required for a driver, besides other configuration data.
Example configuration structure is shown here:
typedef struct
{
pin_name_t out_pin;
pin_name_t cs_pin;
pin_name_t sck_pin;
pin_name_t mosi_pin;
pin_name_t miso_pin;
} click_cfg_t;
Listed in this example are all pins required by the module. User can use this structure to configure the module to work on desired pins, as shown in the following snippet:
click_t click;
click_cfg_t cfg;
cfg.out_pin = PA11;
cfg.cs_pin = PA12;
cfg.sck_pin = PB8;
cfg.mosi_pin = PB9;
cfg.miso_pin = PB10;
click_init(&click, &cfg);
Board support can simplify this process, and make it more portable with mapping macro, defined by module, as shown in next example:
#include "board.h"
...
click_t click;
click_cfg_t cfg;
CLICK_MAP_MIKROBUS(cfg, MIKROBUS_3);
click_init(&click, &cfg);
Every module should define a function for setting up default values for configuration structures.
Naming convention for configuration structures is <module_name>_cfg_t
.
mikroSDK defines pin_name_t
and port_name_t
types for identifying pins and ports on a target MCU. Their size will vary depending on the MCU architecture and port width. Each target MCU defines its own pins and ports in hal_target.h
header file, and is responsible for mapping that number to corresponding module registers and pin masks. Board pin-mapping uses these target pin and port names to identify pin-outs available on development board.
Another way to directly access a pin in mikroSDK 2.0 is by using Pxy, where x is a port letter starting from A and y is a pin number on that port starting from 0. For example, pin PA0 will always be the first pin on the first port of an MCU. PC5 will be the fifth pin of the third port, etc... This applies to all microcontrollers, regardless of their architecture, port letter / number and width.