element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • 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 Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • 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
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • 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
Embedded and Microcontrollers
  • Technologies
  • More
Embedded and Microcontrollers
Blog Port an MBED design to non-MBED - Phase 2b: DigitalOut Class and Blinky example
  • Blog
  • Forum
  • Documents
  • Quiz
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Embedded and Microcontrollers to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 12 Nov 2019 2:46 PM Date Created
  • Views 3142 views
  • Likes 9 likes
  • Comments 17 comments
  • mbed
  • c++
  • hercules
Related
Recommended

Port an MBED design to non-MBED - Phase 2b: DigitalOut Class and Blinky example

Jan Cumps
Jan Cumps
12 Nov 2019

The port of the MBED DigitalOut is complete.

In this blog you can see the internals of this class and how to create a blinky.

 

Blinky

 

#include "includes.h"  // this is the include that replaces MBED.h for ported applications.

// start Hercules HAL includes
#include "HL_gio.h" // specific for Hercules. It's not part of the MBED port.
// end Hercules HAL Includes

DigitalOut led( LED1 );  // initialise the output pin for the LED. This is an MBED ported class.

int main(/* your main loop of your blinky program */) {
  gioInit();  // initialise the device. This example is for Hercules. It's not part of the MBED port.
  while(1) {
     led = !led; // blink/toggle
     wait_ms(500); // a function I wrote that loops the number of miliseconds given as parameter.
   }
}

 

image

 

The core of this example is:

DigitalOut led( LED1 );
while(1) {
     led = !led; // blink/toggle
     wait_ms(500); //
}

 

DigitalOut Header

 

/*
 * DigatalOut.h
 *
 *  Created on: 11 nov. 2019
 *      Author: jancu
 */


/* mbed Microcontroller Library
 * Copyright (c) 2006-2019 ARM Limited
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#ifndef CPP_IMPLEMENTATION_DEPENDENT_CLIENT_PLATFORM_DIGITALOUT_H_
#define CPP_IMPLEMENTATION_DEPENDENT_CLIENT_PLATFORM_DIGITALOUT_H_

#include "hard_includes.h"


class DigitalOut {
public:
  DigitalOut(PinName pin);
  virtual ~DigitalOut();
  DigitalOut &operator= (int value);
  DigitalOut &operator= (DigitalOut &rhs);
  operator int();
protected:
  PinDefinition pinDef;
};


#endif /* CPP_IMPLEMENTATION_DEPENDENT_CLIENT_PLATFORM_DIGITALOUT_H_ */

 

DigitalOut Source

 

/* mbed Microcontroller Library
 * Copyright (c) 2006-2019 ARM Limited
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <DigitalOut.h>

#include "HL_gio.h"

DigitalOut::DigitalOut(PinName pin) {
  // hercules specific= The first 32 bits are the port address, lower 32 bits the pin
  this->pinDef.pin =  pin & 0xffffffff; // the lower 32 bits are the pinnummer
  this->pinDef.port = ((pin & 0Xffffffff00000000) >> 32);

  // if your controller uses APIs to set the pin direction, you'd do that here.
  // I'm using the Hercules HALCoGen utility to set pin directions, so they are in the right state
  // when the pin will be used first.
}

DigitalOut::~DigitalOut() {
}

DigitalOut &DigitalOut::operator= (int value) {
  gioSetBit((gioPORT_t *)(this->pinDef.port), this->pinDef.pin, value);
  return *this;
}

DigitalOut::operator int() {
  return gioGetBit((gioPORT_t *)(this->pinDef.port), this->pinDef.pin);
}

 

Device Specific Declarations Header

 

This file does not contain logic for your program, but definitions for the DigitalOut (and other) classes that are specific for your board.

You see the declarations of the pins (PinName), the values for pin high and low (PinDirection) and a device specific structure PinDefinition that's used in several classes to contain the effective pin info.

I called the file client_board.h. In my final library this file is automatically included.

 

/*
 * client_board.h
 *
 *  Created on: 11 nov. 2019
 *      Author: jancu
 */

/* mbed Microcontroller Library
 * Copyright (c) 2006-2019 ARM Limited
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef CPP_IMPLEMENTATION_DEPENDENT_CLIENT_PLATFORM_CLIENT_BOARD_H_
#define CPP_IMPLEMENTATION_DEPENDENT_CLIENT_PLATFORM_CLIENT_BOARD_H_

// hercules specific: A GPIO pin has a port address 32 bit and a pin number 32 bit.
// To stay compatible with the MBED interface, I kept the pin as single 64 bit number
// with the port in the MSB and pin in the LSB
// this is not efficient for a 32 bit controller. Feel free to modify

typedef uint64_t PinName;

const PinName LED1 = 0xFFF7BC5400000006;  // gioPORTB 6 -- LED2 on launchpad
const PinName LED2 = 0xFFF7BC5400000007;  // gioPORTB 7 -- LED3 on launchpad
// todo: other pins
const PinName NC = 0xffffffffffffffff;

typedef enum {
    PIN_INPUT,
    PIN_OUTPUT
} PinDirection;

typedef struct {
  uint32_t port;
  uint32_t pin;
}PinDefinition;

#endif /* CPP_IMPLEMENTATION_DEPENDENT_CLIENT_PLATFORM_CLIENT_BOARD_H_ */

 

Highlights

 

For the firmware developer, using the classes is easy. Some people like these abstractions, other don't.

Simple code to declare a pin, and to change it:

 

  • Declare a gpio output pin:

DigitalOut led( LED1 );

 

Hercules C equivalent:

// not needed

 

  • Set status:

led = 1;
led = 0;

 

Hercules C equivalent:

gioSetBit(gioPortA, 6, 1);
gioSetBit(gioPortA, 6, 0);

 

  • Toggle status:

led = !led;

 

Hercules C equivalent:

gioToggleBit(gioPortA, 6);

 

  • Get status:

int status = led;

 

Hercules C equivalent:

int status = gioGetBit(gioPortA, 6);

 

Comments and critique on the port are welcome below.

 

Related blog
Use C++ with HALCoGen C Projects

Port an MBED design to non-MBED - Phase 1: compile without errors

Port an MBED design to non-MBED - Phase 2a: DigitalOut Class Constructor
Port an MBED design to non-MBED - Phase 2b: DigitalOut Class and Blinky example
Port an MBED design to non-MBED - Phase 3: InterruptIn Class and example
Port an MBED design to non-MBED - Phase 4: Timeout Class and Blinky example
Port an MBED design to non-MBED - Phase 5: OO Callbacks Simplified
  • Sign in to reply

Top Comments

  • Jan Cumps
    Jan Cumps over 5 years ago in reply to Jan Cumps +3
    15 left The last 3 are dependencies on a header file. I'm deliberately leaving those to the last (they tend to turn into circular definition issues - something different than porting. All other work is…
  • clem57
    clem57 over 5 years ago +2
    Thanks for the example Jan. (Not at all like guest).
  • shabaz
    shabaz over 5 years ago +2
    Hi Jan, Great stuff! : ) From my perspective I think DigitalIn/DigitalOut on mbed are amongst the nicest simplified I/O classes. Very cool : )
Parents
  • Jan Cumps
    Jan Cumps over 5 years ago

    Todos for port exercise completion:

    image

    The list gets smaller

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to Jan Cumps

    15 left

     

    image

     

    The last 3 are dependencies on a header file. I'm deliberately leaving those to the last (they tend to turn into circular definition issues - something different than porting.

    All other work is Related to implement Timers, interrupts and SPI.

    The Callback C++ template is ported.

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to Jan Cumps
    untangle the (non-oo, they are structured programming style) gpio_irq_api.c

     

    I have a possible approach. In my port, provide a C function that gets the port and pin, then selects (search in a registry/array/table) the relevant object for that combination.

    The InterruptIn class is complete from that on. It's able to proceed.

     

    In the native interrupt handler for my platform (it calls the same function regardless the pin - I have to find out from some additional logic what/where the interrupt was triggered) ,

    I can find that port and pin, then call my "port" function....

     

    hang on ...

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to Jan Cumps

    Good news. When a GPIO interrupt fires, I can get a signal in my MBED port from the Hercules HAL layer.

     

    image

     

    Port and pin is available, so I can now try to find a mechanism to find the InterruptIn object that responds to that port and pin.

    I'm reluctant to start using C++ standard lib containers for that - I'm working with a microcontroller.

    Because the number of interrupts I have to watch is limited, a simple loop over an array with key -> InterruptIn pairs may be fast enough.

    The SemTech library that I'm porting uses less than 10 interrupts. Just looping over those and break when a hit is found is fast enough.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to Jan Cumps

    The Interrupt handling is now complete.

    If you look at the Stack: it shows the levels of logic the lib goes through to execute the correct method of the correct class.

     

    image

     

    I put microcontroller specific logic in the gioNotification() function of the Hercules HALCoGen created code,

    and in the interruptfired() function that I created as bridge between that HALCoGen layer and the MBED objects.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to Jan Cumps

    SPI port is now functional (although hard coded for this application to a particular port, bitsize, CS)

    This is a capture of the Hercules microcontroller (SPI master) sending 8 bits to the SemTech SX1276 (SPI slave).

    image

     

    A 1 MHz clock is a bit on the high side - I'll use the frequency from the MBED example, 100 kHz.

     

    The task list has reduced drastically

    image

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to Jan Cumps

    I have a motivation dip image - the last thing to do is port the timer and time-out functions.

    I had done a first attempt 3 weeks ago - it didn't go well (read: did not work). Like most of the activities in this series, I did that on the fly - without fully analysing the libraries.

    For the timer and time-out part, that didn't pan out. I lost oversight during the port event.

    I have since reviewed how these parts are working together and how other platforms port it to the timers.

     

    I'm going to leave this to rest a little longer, then try to port these blocks in a separate project, in isolation.

    Once I have that working, I'll revisit the exercise here to get the LoRa running on the Hercules controller.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to Jan Cumps

    I have a motivation dip image - the last thing to do is port the timer and time-out functions.

    I had done a first attempt 3 weeks ago - it didn't go well (read: did not work). Like most of the activities in this series, I did that on the fly - without fully analysing the libraries.

    For the timer and time-out part, that didn't pan out. I lost oversight during the port event.

    I have since reviewed how these parts are working together and how other platforms port it to the timers.

     

    I'm going to leave this to rest a little longer, then try to port these blocks in a separate project, in isolation.

    Once I have that working, I'll revisit the exercise here to get the LoRa running on the Hercules controller.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to Jan Cumps

    The motivation dip is over. Timeout works.

     

    Port an MBED design to non-MBED - Phase 4: Timeout Class and Blinky example

     

    image

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
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