element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      • Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Freedom development platform
  • Products
  • Dev Tools
  • Freedom development platform
  • More
  • Cancel
Freedom development platform
Documents Processor Expert Tutorial: Creating a Component for an Accelerometer
  • Blog
  • Forum
  • Documents
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Freedom development platform to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Engagement
  • Author Author: FreescaleTools_and_Software
  • Date Created: 9 Aug 2013 2:14 PM Date Created
  • Last Updated Last Updated: 27 Oct 2013 6:40 AM
  • Views 830 views
  • Likes 0 likes
  • Comments 0 comments
Related
Recommended

Processor Expert Tutorial: Creating a Component for an Accelerometer

This tutorial was extracted from Erich Styger blog http://mcuoneclipse.wordpress.com with his agreement.

imageimage

  

If you are a frequent reader of this blog, then you know: I’m a big fan of Processor Expert components. While there are many Processor Expert components delivered with CodeWarrior, it lacks many components and device drivers beside of the normal on-chip peripherals. But value gets added to an embedded project with all the external devices, sensors and actuators. That’s why I have created many more components which are available on my GitHub site. Readers of this blog have asked several times to create a tutorial on how to create a Processor Expert component. So why not working on that on a long Easter weekend full of cold rain and snow?

  

So here we go: a tutorial how to create a Processor Expert component for the MMA8451Q accelerometer found on the FRDM-KL25Z board:

 

MMA8451Q Accelerometer on the FRDM-KL25Z Board 
MMA8451QR1MMA8451QR1 Accelerometer on the FRDM-KL25Z Board
  

 

Warning

  

This tutorial is hard-core, with tips and tricks to work around some issues you might meet. But once you through the traps and pitfalls, creating component can be very addictive. You have been warned :-) . Developing Processor Expert component at least in the current stage of the Eclipse based CDE (Component Development Environment) is not the simplest thing in the world. But very rewarding once you master it.

   

:idea: There exists the non-Eclipse ‘classic’ BeanWizard in CodeWarrior for MCU10.2. This BeanWizard is much easier to use in my view, but not available in MCU10.3 any more, and has been replaced by the Eclipse based one I’m showing here. The good thing with the Eclipse based one is that there is a free ‘Community Edition’ license (see below), while the BeanWizard requires a CodeWarrior Professional Edition License. It is possible to use the classic BeanWizard as well within MCU10.3. If there is interest about trying this out, post a comment and I consider writing a post about how to use the BeanWizard in MCU10.3. :-) On the other side: every new tool (and especially development method) requires a learning phase, and Freescale is constantly improving the CDE for Processor Expert.

  

Overview

 

 

In this tutorial I’m creating a simple driver for the Freescale MMA8451Q accelerometer. The MMA8451QR1MMA8451QR1 is a cool accelerometer with a lot of features, and connected with a I2C bus to the microcontroller. I need that driver for my lecture project, so this is a ‘real’ thing. As such, I’m documenting things as I go, and I plan to frequently update and extend that component. So I plan to post more tutorials.

 

 

 

Processor Expert Component Development Environment (CDE)

 

 

Processor Expert is using ‘components’ to generate software and drivers. While CodeWarrior comes with many components, it is possible to create your own components. The components are written in a ‘C-like’ scripting language.

 

I’m not explaining every concept behind components (see this link as a starting point for other documentation provided by Freescale), as this would be too much as a starter. So here just a few basic concepts and terms:

 

 

  • Methods: These are like normal C functions. An example would be something like ReadAccelerometerValue(), or Neg() for a LED: 

 

 

LED Methods 
LED Methods

 

 
  • Events: This are callback which can be called by the component in an asynchronous way. It is a way to notify the application. An example would

be OnFreefallDetected() or OnError(). 

  

GenericI2C Events 

GenericI2C Events

 

 

 

  • Properties: these are static settings in the component. Things like an I2C address.

 

  

I2C_LDD Properties 
I2C_LDD Properties

 

 

  • Inheritance and Interface: It is possible to re-use another component, either ‘incorporating’ it or to interface with it. For example the LED component inherits from the BitIO component to do low-level bit I/O operations: 

 

 

Inherited Component 

Inherited Component

 

 

The create a component for Processor Expert component, I use the ‘CDE’ (Component Development Environment which is part of CodeWarrior for MCU and the Driver Suite (e.g with IAR). In the past an expensive (Professional) license was required to create Processor Expert components. Recently Freescale has made a ‘Community Edition’ license available which is free of charge for open source/non-commercial components. See this link for details. A time bombed license file is available here on this page.

 

:idea: Future updates of CodeWarrior, Processor Expert and Driver Suite very likely have this community edition license already integrated.

 

Starting Point

 

 

I already wrote a tutorial how to use the MMA8451QR1MMA8451QR1 here, but this was not using a dedicated component for the accelerometer. Since then I have updated the project to use my GenericI2C component:

 

 

Project with GenericI2C 
Project with GenericI2C
  
  

:idea: The reason why I use the GenericI2C component is this: I want to have my software and components working both for devices having LDD (Logical Device Drivers, e.g. for Kinetis) and non-LDD devices (like S08 and ColdFire). The LDD concept in Processor Expert has been very disruptive, and only the recent CodeWarrior for MCU10.3 release has improved the software compatibility. Still, I need an extra software layer for I2C. Painful, but necessary for now. But the advantage is: I can use all my I2C based sensors immediately with my GenericI2C component, independent of the driver architecture Freescale offers me: the power of re-using software :-)

Starting Point

 

 

It is a good idea to have something working as normal C files as starting point. This makes transformation of the driver into a component much easier. For this tutorial, I have the MMA8451QR1MMA8451QR1 working with this simple driver interface:

 

  

 

/*

* MMA8451.h

*

* Created on: Mar 30, 2013

* Author: Erich Styger

*/

#ifndef MMA8451_H_

#define MMA8451_H_

#include "PE_Types.h"

uint8_t MMA8451_GetRaw8XYZ(uint8_t xyz[3]);

uint8_t MMA8451_Deinit(void);

uint8_t MMA8451_Init(void);

#endif /* MMA8451_H_ */

  

The driver implementation looks like this:

   

/*

* MMA8451.c

*

* Created on: Mar 30, 2013

* Author: Erich Styger

*/

#include "MMA8451.h"

#include "GI2C1.h"

/* External 3-axis accelerometer control register addresses */

#define MMA8451_CTRL_REG_1 0x2A

/* MMA8451QR1MMA8451QR1 3-axis accelerometer control register bit masks */

#define MMA8451_ACTIVE_BIT_MASK 0x01

#define MMA8451_F_READ_BIT_MASK 0x02

/* External 3-axis accelerometer data register addresses */

#define MMA8451_OUT_X_MSB 0x01

#define MMA8451_OUT_X_LSB 0x02

#define MMA8451_OUT_Y_MSB 0x03

#define MMA8451_OUT_Y_LSB 0x04

#define MMA8451_OUT_Z_MSB 0x05

#define MMA8451_OUT_Z_LSB 0x06

#define MMA8451_I2C_ADDR (0x1D) /* SA0=1 */

//#define MMA8451_I2C_ADDR (0x1C) /* SA0=0 */

uint8_t MMA8451_GetRaw8XYZ(uint8_t xyz[3]) {

static const uint8_t addr = MMA8451_OUT_X_MSB;

return GI2C1_ReadAddress(MMA8451_I2C_ADDR, (uint8_t*)&addr, sizeof(addr), &xyz[0], sizeof(xyz));

}

uint8_t MMA8451_Deinit(void) {

return ERR_OK; /* nothing to do */

}

uint8_t MMA8451_Init(void) {

static const uint8_t addr = MMA8451_CTRL_REG_1;

static const uint8_t data = MMA8451_F_READ_BIT_MASK|MMA8451_ACTIVE_BIT_MASK;

/* F_READ: Fast read mode, data format limited to single byte (auto increment counter will skip LSB)

* ACTIVE: Full scale selection

*/

return GI2C1_WriteAddress(MMA8451_I2C_ADDR, (uint8_t*)&addr, sizeof(addr), (uint8_t*)&data, sizeof(data));

}

  

And I’m using it like this:

  

/*

* Application.c

*

* Created on: Mar 30, 2013

* Author: Erich Styger

*/

#include "Application.h"

#include "MMA8451.h"

#include "LED1.h"

#include "LED2.h"

#include "LED3.h"

void APP_Run(void) {

uint8_t res=ERR_OK;

uint8_t xyz[3];

LED1_On();

LED2_On();

LED3_On();

res = MMA8451_Init();

while (res==ERR_OK) {

res = MMA8451_GetRaw8XYZ(&xyz[0]);

LED1_Put(xyz[0]>50);

LED2_Put(xyz[1]>50);

LED3_Put(xyz[2]>50);

}

LED1_Off();

LED2_Off();

LED3_Off();

}

 

I’m going now to create a Processor Expert driver for it.

 

 

Creating an Embedded Component Project

 

To create a new component, I select the menu File > New > Embedded Component Project:

 

New Embedded Component Project 

New Embedded Component Project

 

 

 

In the wizard, I give a name for my component:

 

 

Name for New Component 

 

Name for New Component

 

 

:idea: Choosing a good name is important. It is a good idea not to select a name which is not already used, as Processor Expert cannot handle different components with same name. I have found this out the hard way when I created my LED component, not knowing that Freescale has a LED component for the DSC microcontroller family. Additionally, the component name will used as Eclipse project folder name in workspace. As it is not possible to have multiple projects with the same name in the workspace, better to select a component name not producing a conflict. Alternatively a dedicated Eclipse workspace for components can be used. And it will not be easy to change the name of the component afterwards.

  

Pressing next, and I can enter the information for my component:

  

New Component Information 
New Component Information

 

 

I do not need to worry much about the entries, as I can change them later on.

 

 

:idea: the ‘Shortcut’ will be used in my driver as prefix (plus a number) for the methods and events (e.g. MMA1_OnError()). With this in mind, it is a good idea to keep it to 3 to 4 characters only.

 

 

Pressing Finish will create the component project in my workspace:

  

MMA8451Q Component Created 
MMA8451QR1MMA8451QR1 Component Created

 

 

Component Details

 

 

The Component Details editor view shows (most of) the information we just have entered:

 

Component Details Editor View 

Component Details Editor View

 

 

That view can be re-opened any time with the Component Information context menu on the component itself:

 

Component Information Context Menu 
Component Information Context Menu

  

 

:idea: To edit an item in the Component, simply use either the context menu or double-click on it to open an editor view.

 

A ‘*’ mark in the view shows me that the settings have not been saved yet:

  

Dirty Editor Marker 

Dirty Editor Marker

 

 

 

CTRL+S (for Save) will store the settings. A dialog will pop up:

  

Save Dialog 
Save Dialog
  
  

:idea: This dialog will be very annoying. Luckily it is possible to switch it off. For this I use the menu Window > Preferences > Processor Expert > Component Development and switch it off:

 

 

Disabled Save Dialog 

 

Disabled Save Dialog

 

Adding Properties

  

The MMA8451QR1MMA8451QR1 can have two different I2C addresses: either 0x1D or 0x1C.

I want the user to select the address from a drop-down (enumeration list), so first I add a new Enumeration Property Type with the context menu:

  

Adding Enum Property Type 
Adding Enum Property Type

 

 

Then I specify a name and add (‘Add Item’ button) two different enumeration values. The ‘Item Name’ is what the user will see in the drop-down list:

  

Defined Enumeration Property Enumeration 
Defined Enumeration Property Enumeration
   
  

:idea: I explicitly set the ‘Item Value’ to a value I can use later on. That Item Value is technically a string type, but I can use it ‘as is’. You will see later on how this works.

  

Save it with CTRL-S.

Next step is to add the property itself with the context menu:

   

Adding Property 
Adding Property
  
  

For the property, I specify that this is an Enumeration, give it a name (this will be visible to the user). The Symbol name is what I will use in my code. As type I specify the enumeration type I just have defined with its initial Value:

  

Slave Address Property Settings 
Slave Address Property Settings
 
 

 

 

Save the settings with CTRL-S.

 

  

Inherited Component (Interface)

 

 

For my accelerometer, I need to talk to it using the I2C protocol. So I need to interface (or inherit) to such an I2C component. In my case this is the GenericI2C component.

 

 

There are two ways how I can inherit or share a base component:

 

  1. Inherited component (interface): With this, the component I inherit from will be part of my component. A typical case is the LED example from above where the BitIO component is ‘inside’ the LED component, and every access to the BitIO component goes through the LED component.
  2. Link to component: here I have an interface to the component with a ‘link’. That inherited component is not ‘inside’ my component, but ‘outside’. This means that other components can inherit from it too.

 

  :!: Dealing with interfaces is probably the most difficult part in CDE. Messing things up means you can really screw up your component. Better you explore things slowly, and do regular backups of your component.

 

I want to interface (or inherit from) the GenericI2C component. But as there might be other components which need to inherit from it, I use the ‘Link to component‘ way.

 

:!: The way how Processor Expert is using ‘inheritance’ and the terms around this topic are ‘non-standard’, and this can be very confusing, as the inheritance schemes and details are different from other object-oriented terminology.

 

In order to ‘inherit’ (well, ‘link to’), I need first to define the ‘interface‘. The interface is nothing more than basically defining the method and event interface to what I want to interface to. For this I select ‘Inherit to this Component’:

  

 

Inherit to this Component 
Inherit to this Component
 

:!: The term ‘Inherit to this Component’ can be very misleading (again): what it does here is defining an interface.

 

 

This triggers this dialog:

 

 

Confirmation dialog 

Confirmation dialog

 

 

:?: Not sure why this dialog even shows up if my component settings are all saved?

 

 

Then, in the following dialog I select the GenericI2C component:

 

 

Inheritance Wizard 
Inheritance Wizard
 

:!: Note the warning in the dialog header. This is because I inherit from GenericI2C, but I use a different identifier (I2C) for my interface. The reason is that if I’m not doing this, CDE will create a global interface for me, which I definitely do not want and need. I need a local interface to a global component. This was supported out of the box in the old classic BeanWizard, but the Eclipse based only supports this with the changes I’m doing in this step and below. I want to have my interface named ‘I2C’ (to have it generic), and I want to have the GenericI2C assigned as template. More on this in the next steps.

 

 

Pressing Next will get me to a dialog where I can specify the type of inheritance. As I want to share the GenericI2C component, I select ‘shared usage’:

 

 

Shared usage 
Shared usage

 

 

Next, I can specify which methods and events I want to use: I select ‘Inherit: Yes’ for ReadAddress() and WriteAddress(), as I want them to be used from my component:

 

 

Interface definition 
Interface definition
 

:idea: I don’t need to worry too much about the interface definition in this dialog. I can change things at a later stage. With this, I even can not inherit anything here, and change my mind later on.

 

 

Pressing next gets me to the next dialog:

 

 

Multiple Inheritance 
Multiple Inheritance

 

 

 

 

This introduces another concept: multiple Inheritance. Similar to the concepts above, this is probably not the same what you would typically understand under ‘multiple inheritance’ in object-oriented languages. What it means here is that you can interface to different components. For simplicity, I keep the settings (as I can change things later) and press Next.

In the next dialog, I cannot change anything, so time now to press ‘Finish’:

 

 

Select programming language 
Select programming language

 

 

I will notice that the interface has been added to my workspace as a folder:

 

 

Interface added to Workspace 
Interface added to Workspace

 

 

:!: The fact that the interface has been added as a folder into my workspace has the consequence that I cannot have multiple interfaces with the same name inside my workspace, which is a problem, as I want to have interfaces like MMA8451Q\GenericI2C and e.g. RTC3232\GenericI2C. Because it would be the same interface name (even for different components), this is not supported with this CDE approach. As a workaround I use different workspaces.

 

Property for the Interface

 

 

I want to be able to select my newly created interface as a property in my component. For this, I could a new property if CDE has not already added one:

 

 

Adding new Property for Link to Component 
Adding new Property for Link to Component

 

 

But CDE should already added the property if you followed the above steps. If not, use the ‘Add Property’ context menu as shown in the previous screenshot.

 

 

Added Property for Inherited Component 
Added Property for Inherited Component
 
 

 

 

Next, I’m verifying the settings and extend the description:

 

 

Link to Component Setting 
Link to Component Setting

 

 

The ‘Item Name’ is what will be shown in the user interface, while the ‘Symbol’ is what I will use in my code. As InterfaceName I select the just created interface which shows up under my Component name (MMA8451Q\I2C.int).

  

 

 

Assigning Template to Inherited Interface

 

 

Remember the above step where I decided to use ‘I2C’ instead of ‘GenericI2C’? This means, that I have an interface named ‘I2C’, and now need to assign a ‘Template’ to it so Processor Expert knows which components are ‘compatible’ with it.

   

 

:idea: The fact that I need to register a template to an inherited interface is problematic. It means that without assigning a template of a ‘yet-to-built’ component, I can not interface with it. At least this is what happened to me: If I do not register a template, I cannot use it as interface. For example if I would implement another ‘GenericI2C_Other’ component, even if the interface matches, without having it assigned as template to the interface I cannot use it. And I need to be careful not to use a local template (within the component), because then I cannot select a global component for my interface. The best way is always to choose an interface name which is not likely to conflict with a component name.

 

 

So I’m going to register the GenericI2C component as template to the interface. For this I open the interface file (*.int) inside the component structure and search for :

 

 

Interface file open in text editor 
Interface file open in text editor

 

 

Then replace the I2C template with the GenericI2C one:

 

 

  <Registration> <Template>GenericI2C</Template> </Registration>

 

 

Later, if you want to allow more components to interface with your component, simply add extra Template lines within the block.

 

 

:idea: It is possible to register a template to an interface with the CDE GUI too: for this I would need to import the interface, and then register the template. But this will create an interface project folder in my workspace, and for whatever reason somehow my interfaces and templates got screwed up. So at least to me just using a text editor was faster and worked always :-) .

 

Adding Methods

 

 

Now I’m going to the following methods to my driver:

 

  • Init(): Initialize the driver, allocates any needed memory data structure.
  • Deinit(): Counterpart to Init().
  • GetRaw8XYZ(): returns the raw 8bit accelerometer values.

 

To add a new method, I use the context menu ‘Add Method’:

 

 

Adding Method 
Adding Method

 

 

First, I configure the Init() method:

 

 

Init Method 
Init Method

 

 

Using the ‘Source code’ tab I switch to the implementation of this method:

 

 

Source Code of Init Method 
Source Code of Init Method

 

 

Next, I copy my existing driver code into the block after %CODE_BEGIN:

  

 

static const uint8_t addr = MMA8451_CTRL_REG_1;

static const uint8_t data = MMA8451_F_READ_BIT_MASK|MMA8451_ACTIVE_BIT_MASK;

/* F_READ: Fast read mode, data format limited to single byte (auto increment counter will skip LSB)

* ACTIVE: Full scale selection

*/

return GI2C1_WriteAddress(MMA8451_I2C_ADDR, (uint8_t*)&addr, sizeof(addr), (uint8_t*)&data, sizeof(data));

 

 

Copied Driver Init Code 
Copied Driver Init Code

  

 

:!: Only make changes between %CODE_BEGIN and %CODE_END, unless you know exactly what you are doing!

 

 

Wait, something is not ok. I’m have spent so much time above for my I2C interface, so I better use it ;-) . To use an inherited interface method, the following syntax is used:

 

 

%@InterfaceName@'ModuleName'%.MethodName

 

 

With this, I’m changing my return statement to

 

return %@I2C@'ModuleName'%.WriteAddress(MMA8451_I2C_ADDR, (uint8_t*)&addr, sizeof(addr), (uint8_t*)&data, sizeof(data));

 

Next, I need to add the MMA8451QR1MMA8451QR1 register #defines.

For this I open the driver and search for BW_CUSTOM_VARIABLE_START:

 

 

Driver with custom variables start area  
Driver with custom variables start area
 
 

That’s just the beginning of my driver module, so a good place for my defines I want to keep inside my implementation module:

 

 

 

/* External 3-axis accelerometer control register addresses */

 

#define MMA8451_CTRL_REG_1 0x2A

/* MMA8451QR1MMA8451QR1 3-axis accelerometer control register bit masks */

#define MMA8451_ACTIVE_BIT_MASK 0x01

#define MMA8451_F_READ_BIT_MASK 0x02

/* External 3-axis accelerometer data register addresses */

#define MMA8451_OUT_X_MSB 0x01

#define MMA8451_OUT_X_LSB 0x02

#define MMA8451_OUT_Y_MSB 0x03

#define MMA8451_OUT_Y_LSB 0x04

#define MMA8451_OUT_Z_MSB 0x05

#define MMA8451_OUT_Z_LSB 0x06

#define MMA8451_I2C_ADDR (0x1D) /* SA0=1 */

//#define MMA8451_I2C_ADDR (0x1C) /* SA0=0 */

 

 

I’m adding my defines there:

 

defines added  
defines added
 
 

But what about the I2C address defines? I have now a property in the component for this. So I can reference to the value of the property using

 

%SymbolName

 

 

I have used the symbol name ‘I2CSlaveAddress’, so I can change it to

 

#define MMA8451_I2C_ADDR (%I2CSlaveAddress) /* I2C slave device address as set in the properties */

 

 

With this knowledge, it is easy to add the Deinit() method properties and code:

 

 

Deinit Method Properties  
Deinit Method Properties

 

 

Deinit() driver source code  
Deinit() driver source code
 
 

 

 

If you are a good C/C++ programmer, you probably have spotted a bug in CDE for the above driver code: there is no ‘void’ in the method parameter list :-( .

In C, the following

  

void foo();

  

 

is not the same as

 

void foo(void);

 

The first declaration does not declare any parameters (so it could be zero, or one parameter, or any number of parameter), while the second version with ‘void’ defines the interface that there are no parameter. While the ‘classic’ BeanWizard properly uses (void) for a method without parameters, this is wrong in CDE for MCU10.3. To fix this, I edit the .drv sources and add the void to it, both for the declaration and the implementation:

 

 

Fixed Driver Code Declaration  
Fixed Driver Code Declaration

 

 

Fixed Driver Code Definition  
Fixed Driver Code Definition
 

Next to add the GetRaw8XYZ() method:

 

  

GetRaw8XYZ Method Properties  
GetRaw8XYZ Method Properties
 
 

This method requires a parameter:

 

 

Added Parameter  
Added Parameter
  

:?: This translates into ‘uint8_t *xyz’ which is not exactly the same as ‘uint8_t xyz[3]‘. The classic BeanWizard has the ability to specify parameters of any kind, while the Eclipse based CDE misses that capability. While it would be possible to define a custom type, I’m not going down that road here.

 

 

GetRaw8XYZ() Method Source Code 

GetRaw8XYZ() Method Source Code

 

 

static const uint8_t addr = MMA8451_OUT_X_MSB;

 

return inherited.I2C.ReadAddress(MMA8451_I2C_ADDR, (uint8_t*)&addr, sizeof(addr), &xyz[0], 3);

 

 

 

 

Changing Icon

 

 

Our shiny component only will look professional, if it has a nice icon :-) . It is possible to create a custom icon for it, as long it is a 16×16 pixel bitmap file.

   

 

:!: Note: the pixel at (0,0) defines the transparent background color. See this post.

 

 

I can create a new icon (16×16 pixels). The easiest way is to copy an existing one (e.g. from my GitHub repository) and modify it with Paint or any other Windows Bitmap program.

I recommend to place the component icon bitmap file into the Beans folder of the component, with the same name as the component (MMA8451Q.bmp):

 

 

MMA8451Q Component Icon  
MMA8451QR1MMA8451QR1 Component Icon
 
   

 

 

Then I use the Open button:

 

 

Open for a new Icon  
Open for a new Icon
 
 

Then browse to the location where the bitmap file is and then open that file:

 

 

:!: Note: select *.bmp as filter.

  

MMA8451Q Bitmap File  

MMA8451QR1MMA8451QR1 Bitmap File

 

 

 

 

Now I have a cool icon for my component:

 

 

Updated Icon for Component  
Updated Icon for Component
 

:!: There is bug in the current CDE (at least in CodeWarrior for MCU10.3): the user icon is not shown in the Components Library view. It still shows the default user one. The reason seems to be that the bitmap conversion/settings are not stored properly. I still have the ‘classic’ BeanWizard, and with this one I’m able to convert and set the bitmap correctly.

 

Trying it out

 

 

So far my Components Library view is not showing my new component: I need first to refresh the list:

 

 

 

Refresh Components  
Refresh Components
  
 

 

 

With this, my new component shows up:

 

 

MMA8451Q in Component Library  
MMA8451QR1MMA8451QR1 in Component Library
  

:idea: In case the component shows up with the default/blue icon, then this is probably the Icon problem I have described above. Converting/setting the Icon with the classic BeanWizard works.

 

 

I double-click on the component to add it to my project:

 

 

Creating new Component  
Creating new Component
 

 

 

Then it will ask me either to create a new shared component for I2C, or to use an existing one. As I already have a GenericI2C component in my project, I can select the existing one:

 

  

Selecting Shared Component  
Selecting Shared Component
  
 

In the component Inspector, I see now the default I2C slave address plus the I2C Bus interface selected:

 

  

Component Inspector  
Component Inspector
 
 

 

 

For the Slave Address, I can select one of the enumeration values I have defined earlier:

 

 

Drop Down with Predefined Enumeration Values  
Drop Down with Predefined Enumeration Values
 
 

With the new component added to the project, it shows up with the three methods as defined:

 

New Component with Methods  
New Component with Methods
  
 

There is one problem: sometimes the methods are marked with an ‘x’. This means they are disabled. I use the context menu to enable them:

  

Toggle to Enable the Method 

Toggle to Enable the Method

  

 

:!: I believe this is a bug in CDE in MCU10.3, as I feel I have my settings correct, and it works as expected with the classic BeanWizard.

 

 

With this, all my methods are enabled:

  

All Methods enabled 

All Methods enabled

 

 

Generated Code

  

Time to inspect the generated code:

   

 

/** ###################################################################

 

** THIS COMPONENT MODULE IS GENERATED BY THE TOOL. DO NOT MODIFY IT.

** Filename : MMA1.c

** CDE edition : Standard

** Project : ProcessorExpert

** Processor : MKL25Z128VLK4

** Component : MMA8451QR1MMA8451QR1

** Version : Component 01.003, Driver 01.00, CPU db: 3.00.000

** Compiler : GNU C Compiler

** Date/Time : 2013-03-31, 20:24, # CodeGen: 18

** Abstract :

**

** Settings :

** Contents :

** Init -

** Deinit -

** GetRaw8XYZ -

**

** License : Open Source (LGPL)

** Copyright : (c) Copyright Erich Styger, 2013, all rights reserved.

** http://www.mcuoneclipse.com

** This an open source software in the form of a Processor Expert Embedded Component.

** This is a free software and is opened for education, research and commercial developments under license policy of following terms:

** * This is a free software and there is NO WARRANTY.

** * No restriction on use. You can use, modify and redistribute it for personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.

** * Redistributions of source code must retain the above copyright notice.

** ###################################################################*/

/* MODULE MMA1. */

#include "MMA1.h"

/* External 3-axis accelerometer control register addresses */

#define MMA8451_CTRL_REG_1 0x2A

/* MMA8451QR1MMA8451QR1 3-axis accelerometer control register bit masks */

#define MMA8451_ACTIVE_BIT_MASK 0x01

#define MMA8451_F_READ_BIT_MASK 0x02

/* External 3-axis accelerometer data register addresses */

#define MMA8451_OUT_X_MSB 0x01

#define MMA8451_OUT_X_LSB 0x02

#define MMA8451_OUT_Y_MSB 0x03

#define MMA8451_OUT_Y_LSB 0x04

#define MMA8451_OUT_Z_MSB 0x05

#define MMA8451_OUT_Z_LSB 0x06

#define MMA8451_I2C_ADDR (0x1D) /* I2C slave device address as set in the properties */

/*

** ===================================================================

** Method : MMA1_GetRaw8XYZ (component MMA8451QR1MMA8451QR1)

**

** Description :

** Returns in an array the x, y and z accelerometer as 8bit values.

** Parameters :

** NAME - DESCRIPTION

** uint8_t xyz - Pointer to an array of three unsigned 8bit

** values which are used to return the accelerometer

** values.

** Returns :

** uint8_t -

** ===================================================================

*/

uint8_t MMA1_GetRaw8XYZ(uint8_t *xyz)

{

static const uint8_t addr = MMA8451_OUT_X_MSB;

return GI2C1_ReadAddress(MMA8451_I2C_ADDR, (uint8_t*)&addr, sizeof(addr), &xyz[0], sizeof(xyz));

}

/*

** ===================================================================

** Method : MMA1_Deinit (component MMA8451QR1MMA8451QR1)

**

** Description :

** Counterpart to Init() method.

** Parameters :

** NAME - DESCRIPTION

** Returns :

** uint8_t -

** ===================================================================

*/

uint8_t MMA1_Deinit(void)

{

return ERR_OK; /* nothing to do */

}

/*

** ===================================================================

** Method : MMA1_Init (component MMA8451QR1MMA8451QR1)

**

** Description :

** Initializes the device driver

** Parameters :

** NAME - DESCRIPTION

** Returns :

** uint8_t -

** ===================================================================

*/

uint8_t MMA1_Init(void)

{

static const uint8_t addr = MMA8451_CTRL_REG_1;

static const uint8_t data = MMA8451_F_READ_BIT_MASK|MMA8451_ACTIVE_BIT_MASK;

/* F_READ: Fast read mode, data format limited to single byte (auto increment counter will skip LSB)

* ACTIVE: Full scale selection

*/

return GI2C1_WriteAddress(MMA8451_I2C_ADDR, (uint8_t*)&addr, sizeof(addr), (uint8_t*)&data, sizeof(data));

}

/* END MMA1. */

/*

** ###################################################################

**

** This file was created by Processor Expert 10.0 [05.03]

** for the Freescale Kinetis series of microcontrollers.

**

** ###################################################################

*/

 

 

The code looks fine so far.

 

:?: You might notice that the return ‘hints’ have not been added to the comments. Not sure why CDE does not handle this properly, as I have specified the hints text in the method properties?

 

I can now change my Application.c to use my new driver generated by the component:

 

 

/*

 

* Application.c

*

* Created on: Mar 30, 2013

* Author: Erich Styger

*/

#include "Application.h"

#if 0

#include "MMA8451.h"

#else

#include "MMA1.h"

#endif

#include "LED1.h"

#include "LED2.h"

#include "LED3.h"

void APP_Run(void) {

uint8_t res=ERR_OK;

uint8_t xyz[3];

LED1_On();

LED2_On();

LED3_On();

#if 0

res = MMA8451_Init();

#else

res = MMA1_Init();

#endif

while (res==ERR_OK) {

#if 0

res = MMA8451_GetRaw8XYZ(&xyz[0]);

#else

res = MMA1_GetRaw8XYZ(&xyz[0]);

#endif

LED1_Put(xyz[0]>50);

LED2_Put(xyz[1]>50);

LED3_Put(xyz[2]>50);

}

LED1_Off();

LED2_Off();

LED3_Off();

}

 

Build, download and run. And it works :-)

  

 

Application running with new Component Code  
Application running with new Component Code
 
 

Summary

 

If you are still reading this: Congratulations! You are a Component Warrior and you made it up to here :-) . Seriously, things look very complicated at the beginning, and CDE development requires a learning curve, similar to learning a new language and tools. But as you maybe imagine with the components I have developed, it very well pays off. And with the outlook that things likely get easier and simpler in the future, the future is bright for Processor Expert Component development. :-)

 

 

Sources and further reading

 

The CodeWarrior project used in this tutorial is available here, and the MMA8451QR1MMA8451QR1 component is here. A ‘Getting Started’ on CDE can be found here. Additionally have a look at the Freescale CDE Home Page.

 

Happy Componentizing :-)

  • code_generation_tool
  • compiler
  • cortex-m0+
  • processor_expert
  • freescale
  • Cortex-M
  • kinetis
  • cortex
  • frdm-kl25z
  • kinetis-l
  • cortex-m0
  • component
  • arm
  • freedom
  • Share
  • History
  • More
  • Cancel
  • Sign in to reply
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube