The Internet of Things on AWS – Official Blog

Connecting with mobile BLE to AWS IoT Core using FreeRTOS and Nordic nRF52840-DK

As an IoT solution architect, customers often ask me how they can connect to AWS IoT Core (cloud) using a microcontroller unit (MCU). One solution is to use Bluetooth Low Energy (BLE) as the connection from the MCU to a mobile device; from there, the mobile device connects to the cloud. BLE works for consumer IoT device use cases such as thermostats, door locks, connected bicycles, smart watches, and many others.

In this blog, I demonstrate how to use a Nordic nRF52840-DK board (MCU) to connect to AWS IoT Core using BLE with an iOS mobile app. I show two ways to connect to AWS IoT Core (cloud): first by directly using BLE and passing data into AWS IoT Core using MQTT, and second by using GATT setup to pass data through to AWS IoT Core using BLE and your mobile phone.


Solution overview

In our solution, we will use Nordics nRF52840-DK with FreeRTOS and will carry out the following tasks (these are commonly required tasks in embedded development to connect MCUs to the cloud using BLE and mobile applications):

First, we will do the embedded-side development:

  1. Set up the hardware (MCU with serial port communication with the computer).
  2. Set up firmware (if needed to communicate with the computer).
  3. Set up and configure FreeRTOS on the MCU.
  4. Set up, configure, and deploy FreeRTOS BLE application on the MCU.

Then, we will do the cloud side tasks:

  1. Set up a BLE IoT thing in AWS IoT Core.

Then, we will do the mobile app client tasks:

  1. Configure and deploy the application to our mobile phone (iOS).

Once we have completed following tasks, we will be able to test the complete end-to-end process of MCU connecting to AWS IoT Core using MQTT as well as Custom GATT MQTT settings from Mobile client, giving us insight on many different ways we can connect to AWS IoT.

Solution Diagram


To set up your hardware

Connect your host computer to the USB port labeled J2, located directly above the coin cell battery holder on your Nordic nRF52840 board (see the highlighted box in the following picture).


To set up your terminal emulator

You need a terminal emulator to read data between your desktop and board using serial connection. This terminal emulator will be used to read the output from the board, as well as write to the board such as firmware and FreeRTOS code. For this blog, you can use the following:

  • For Windows: TeraTerm
  • For Linux and MacOS: GNU Screen (follow configuration using settings here)

In your terminal emulator, run the following:

ls /dev/cu.* 

If your device does not show up, you may need a serial port driver for the board (refer to SEGGER J-Link here to set up).

If the light on your board is constantly blinking, then its not connected to your laptop. When connected, a green light pulsates on LED5 (see LED5 printed on the board).

To set up the embedded development IDE and connect to your device

Download and set up SEGGER Embedded Studio and choose the Embedded Studio for ARM option. With Nordic devices, you can obtain a free license here. This also installs JLink—if it didn’t install, you can install from here.


Open SEGGER and install the Nordic CPU supported package:

  1. From the top menu, select Tools, then select Package manager.
  2. Search for “nRF CPU Support Package” and then install the package.


  1. Once it’s connected, open your operating system file manager (for Mac: Finder, for Windows: File Explorer) to check that the nRF52840-DK has appeared as a removable drive named “JLINK”. It will be same for all operating systems.
  2. Now, configure the terminal emulator settings for this. You will need your serial port details.
    1. Run the following command in the command line: ls /dev/cu.*

The following output should be shown:


A device looks similar to: /dev/cu.usbmodem0006833844771. The device in this example is connected.

Next, we will configure the SEGGER terminal emulator.

  1. From the top menu, select Tools.
    1. Select Terminal Emulator, then select Properties.
    2. Update the settings as follows:
      1. Baud Rate: 115200
      2. Data bits: 8
      3. Parity: None
      4. Port: <selected output from above>
      5. Stop Bits: 1


Now connect to the device:

  1. From the top menu, select Tools.
  2. Select Terminal Emulator, then select Connect <device port>.



Once the MCU is connected, you will see the device Connect port greyed out, as shown:


To set up FreeRTOS with BLE and an AWS IoT thing

Open a command line and clone the FreeRTOS repo. Use the following command:

git clone --recurse-submodules

To set up a BLE IoT thing for our Nordic board

In this section, we will set up the IoT thing (MCU board) in AWS IoT Core (cloud side), name it nrf52840BLE, and then register without a certificate. By now, you should have already set up “ iOS SDK for FreeRTOS Bluetooth devices.” For Android, follow the steps here. Now, let’s go ahead and set up the cloud side and create your AWS IoT thing.

Create a thing

  1. Open the AWS IoT console.
  2. In the navigation pane, select Manage, then select Things.
  3. Select Create things, then select Create single thing and give it a name: nrf52840BLE. (Leave the rest of the settings as default.)
  4. In the Device Certificate section, select Skip creating a certificate at this time.

Now that the thing is created, let’s find its endpoint:

  1. In the navigation pane, select Manage, then select Things.
  2. In the search bar, search for nrf52840BLE, then choose nrf52840BLE.
  3. From the navigation pane, select Interact, and note the endpoint as shown in the following screenshot:


Next, we need to create Amazon Cognito identities. To do that, we will need to create an Amazon Cognito user pool and ID pool.

To create an Amazon Cognito user pool: Create a user pool

  1. Open the Amazon Cognito console, choose Manage user pools, then Create a user pool.
  2. Give pool name: nrfdemo.
  3. From navigation pane, choose App Clients, then Add an app client, and give it a name: nrfappclient.
  4. From navigation pane, choose Review defaults, choose Create pool.
  5. From the navigation pane, under General settings, note down Pool id (as shown in the following image).
  6. From the navigation pane, select App Clients and then select Show details. Make note of the App client id and the App client secret.


To create an Amazon Cognito identity pool: create an ID pool

  1. In the Amazon Cognito console, choose Manage Identity Pools, select Create new identity pool.
  2. In Identity pool name give name nrfdemoidpool.
  3. Expand Authentication providers, choose the Cognito tab, and then enter your user pool ID and app client ID.
  4. Select Create Pool.
  5. Expand View Details, and make a note of the two IAM role names (see the following screenshot), Choose Allow to create the IAM roles for authenticated and unauthenticated identities to
  6. access Amazon Cognito.
  7. Select Edit identity pool. Make a note of the identity pool ID – e.g., eu-central-1:1abcde01-1a0b-1ab6-a12b-ab1abc12a123

Make note of the IAM roles.


To create and attach an IAM policy to the authenticated identity – IAM policy to enable Amazon Cognito ID to connect to AWS Cloud

  1. Open the IAM console, and from the navigation pane, choose Roles.
  2. Find and choose your authenticated identity’s role,
    1. Find those roles in the IAM created in previous step (mine were: Cognito_nrfdemoidpoolAuth_Role and Cognito_nrfdemoidpoolUnauth_Role).
  3. Choose Attach policies, and then choose Add inline policy.
  4. Choose the JSON tab, and paste the following JSON code.
  5. Give the policy name: IAMnrfPolicy.
  6. Select Create Policy.


At this point, we have set up an IoT thing for our MCU and connectivity credentials, which we will use to authenticate in the mobile app when MCU establishes the BLE connection. Make sure to keep your AWS IoT and Amazon Cognito information on hand. You need the endpoint URL and IDs (created in the previous steps) to authenticate your mobile application with the AWS Cloud.

Set up your FreeRTOS environment for BLE

To set up a FreeRTOS BLE Mobile SDK demo application

  1. Download the relevant SDK (I will use instructions for iOS.):
    • For iOS, clone the repo and set up the pod per the instructions here.
    • For Android, clone the repo and follow the instructions here.
  2. Once you have cloned the repo and set up the pod using cocoapods, add the following in the Podfile which exists under [amazon-freertos-ble-ios-sdk/Example/AmazonFreeRTOSDemo/Podfile]:

pod 'AmazonFreeRTOS', :git => '', :tag => '1.2.0'

Note: In Xcode, if you get following files for pod showing up as red, as seen in the following screenshot, then run the following command in your workspace directory:

pod install

This will install all the dependencies for you.

xcode_afr_demo terminal_screen

  1. Close Xcode, re-open the project, and clean build.

Finally let’s create an IoT policy on AWS IoT for this. (If you no longer want to continue with this demo solution after you complete the steps, make sure to delete the policy later.)

  1. Open the AWS IoT console.
  2. In the navigation pane, select Secure.
  3. In Secure, select Policies.
  4. Choose Create.
    1. Give the poolicy a name: nrfdemopolicy
    2. In Action, type in iot:*
    3. In Resource ARN, type in *
    4. Select Allow in Effect section.
  5. Complete by selecting Create.


Modify iOS Mobile app using Xcode

To configure SWIFT code

We will need to modify our iOS mobile app in swift code to let it know which region and which IoT policy to use and which MQTT topic to send the data over to.

  1. Open Xcode, then open the following file. We will modify constants as in the following screenshot.


Other regions such as: EUWest1, EUWest2, EUWest3, EUNorth1, EUSouth1 are also available these can be found in: AWSServiceEnum.h file select the region relevant to you. As shown, I’m using Frankfurt region (EU-Central-1).


  1. Modify the json file which will use the relevant AWS Cognito UserPool and IdPool we created earlier.



Now we can proceed to build the project. (Make sure you are using your own code signing credentials and not Amazon-provided defaults, as this will fail to build).

  1. In Xcode top menu, select Product.
  2. Choose Clean Build folder, then Build.
  3. Once the build completes, select Product, and choose Run.

This will deploy the app your to iOS device and will code sign to run it on the device.

FreeRTOS Mobile App

  1. Select Create account. This will send code to the email you requested and confirm.

By using following these instructions you have completed the mobile app development, deployment, and its build. So, now the iOS BLE mobile app is completed, let’s deploy the FreeRTOS BLE Demo app to MCU.

To deploy FreeRTOS demo BLE code to the MCU

Switching back to the MCU, you will need to set up instructions using details here. Earlier we already had connected to the MCU using SEGGER embedded studio—now, let’s deploy FreeRTOS and demo code to connect to the mobile app to send data to AWS IoT Core.

For FreeRTOS release, we are using release of 05/26/2021.

To configure the project

  1. In this “Getting started with the Nordic nRF52840-DK” tutorial, when you get to the “Configure your project section”, note down your AWS IoT endpoint and modify #define constant code in following file:
  2. Update the endpoint and thing name as seen in the following screenshot:


  1. Check that the BLE GATT Demo is enabled under amazon-freertos folder. To do this, go to vendors/nordic/boards/nrf52840-dk/aws_demos/config_files/iot_ble_config.h, and add #define IOT_BLE_ADD_CUSTOM_SERVICES ( 1 ) to the list of define statements.

xcode header file

  1. Increase Bluetooth pairing timeout for the mobile app since you will be paring the device with your phone. To pair the MCU with mobile client you will be required to enter y’ to accept the pairing. To ensure timeout doesn’t occur, let’s increase the timeout in the following file: iot_ble_config.h
  2. Update the following line to 60 seconds: #define IOT_BLE_NUMERIC_COMPARISON_TIMEOUT_SEC ( 60 )
  3. Save the file.

To Build and run the project FOR MCU in SEGGER

  1. If this is the first time that you are running the demo on this board, you need to flash a bootloader to the board before the demo can run. Run the following: FreeRTOS Folder / projects/nordic/nrf52840-dk/ses/aws_demos/bootloader/bootloader.emProject
  2. When you get the following prompt, select O.K.

jlink firmware

To build the demo BLE app for MCU

  1. Open following FreeRTOS project in SEGGER Embedded Studio: FreeRTOS Folder/projects/nordic/nrf52840-dk/ses/aws_demos/aws_demos.emProject
  2. Modify the following file (application_code/common_demos/ble/mqtt_ble/mqtt_demo_ble_transport.c) string to a different message than “hello world.” I will use following test (feel free to use what you prefer): "Hello BLE message from Nordic nRF52840-DK MCU"


segger embedded studio

  1. Save the project, right click and build the project (as shown in the previous screenshot).
  2. Once built, select Target > Connect J-Link, and then choose Debug, Go.
  3. Once the build is done, go to Target and Connect J-Link.
  4. When complete, open the FreeRTOS app on your iOS device.
  5. You will see the nRF MCU will show up on the devices. Select your device and then select Pair.

Bluetooth Pairing Request

ios ble devices

  1. Once you select Pair on your mobile device, enter ‘y’ on the serial terminal emulator (computer) for the MCU to be accepted with the pairing.
    • For MacOS / Linux: screen /dev/cu.usbmodem0006837380271 115200
    • For Windows (using TeraTerm): In the Terminal Press ‘y’ on the screen confirm Bluetooth pairing.

Optional: To exit the screen app, press CTRL+A and K and press y to exit the screen app.

To see messages coming into AWS IoT Core

  1. Open the AWS IoT console.
  2. In the navigation pane, select Test.
  3. In Subscribe to a topic, enter ‘#‘ to capture all topics.
  4. Choose Subscribe.

iot core test client

You will see messages appearing in the AWS IoT console. Congratulations, you have connected your Nordics MCU using FreeRTOS BLE from MCU and using FreeRTOS iOS mobile app to act as MQTT Proxy to send data to AWS IoT Core.

To enable the custom BLE GATT server demo

Now that we have completed MQTT over BLE to AWS IoT Core, let’s do the test using Custom BLE MQTT GATT to send data to AWS IoT Core using GATT setup:

First we will modify the following header file to make sure Custom BLE GATT server demo is enabled for Mobile iOS client application.

  1. Open following file: FreeRTOS /vendors/nordic/boards/nrf52840-dk/aws_demos/config_files/aws_demo_config.h
    • Add following #define CONFIG_BLE_GATT_SERVER_DEMO_ENABLED.

Once changes are done you will see the code as seen in the following screenshot:

aws demo config header file

  1. Save the project.
  2. Right-click, choose Clean, then Build.
  3. Once the build is done, navigate to Debug, and choose Go.
  4. On the iOS mobile app side, open the FreeRTOS app.
  5. Select the MCU. When you get following option, choose Start Counter:


Start Counter

Finally, to see data coming into AWS IoT Core:

  1. Open the AWS IoT console.
  2. In the navigation pane, select Test.
  3. In Subscribe to a topic, type in “#” to capture all topics, as shown in the following screenshot.
  4. Choose Subscribe.

iot core test client mqtt messages

Cleaning up

If you followed along with this solution, complete the following steps to avoid incurring unwanted charges to your AWS account.

AWS IoT Core

  • In the Manage section, delete the Thing (nrf52840BLE)
  • In the Secure section, remove the Policy (nrfdemopolicy)

Amazon cognito

  • Delete the User pool (nrfdemo)
  • Delete the Identity pool (nrfdemoidpool)


  • Delete the roles:
    • Cognito_nrfdemoidpoolAuth_Role
    • Cognito_nrfdemoidpoolUnauth_Role
  • Delete IAM Policy (IAMnrfPolicy)


In this blog, first, I demonstrated how to set up our MCU and connect to our desktop. Second, I built our mobile app which acts as our proxy for BLE. Third, I set up our demos on the MCU and built and deployed it to the MCU. Finally, I sent data from the MCU through a mobile phone app BLE proxy, as well as a custom BLE GATT server into AWS IoT.

This walkthrough demonstrates the flexibility of using FreeRTOS with our Nordics nRF52840-DK MCU; combined with BLE, we have easy connectivity. FreeRTOS does the heavy lifting, allowing us to focus on custom application code for MCU.

This blog shows how several basic components and native AWS features allow you to simplify both IoT application development and delivery of MCU data, which customers can use further once in the cloud to carry out analytics and historic data analysis. From MCU (using FreeRTOS) to AWS IoT Core, you can set up and deploy your solution with minimal lines of code and use sample applications provided by FreeRTOS. In addition, once the data streams into AWS IoT Core, it is easy to develop and customize dashboards and apply machine learning models that enable teams to iterate quickly and achieve data-driven insights from your end devices. To learn more, check out the FreeRTOS and AWS IoT Core product detail web pages.


About the author

Syed Rehan IoT architect picture Syed Rehan is a Global Sr. Specialist Solutions Architect at Amazon Web Services and is based in London. He is covering global span of customers and supporting them as lead IoT/ML Solution Architect. Syed has in-depth knowledge of IoT/ML and cloud and works in this role with global customers ranging from start-up to enterprises to enable them to build IoT solutions with the AWS cloud eco system.