Wednesday, March 2, 2022

Software timers and Ring Buffered UART Com for LPC824 MCU

In this article, I would like discuss about using LPC82x MCU with MCUXpresso IDE. I will use LPCXpresso824-MAX Board as a hardware platform.



Environment Setup

Firstly, download 'MCUXpresso IDE' from NXP website and install it. Also download SDK for LPCXpresso824-MAX Board and 'drag and drop' the downloaded zip file onto MCUXpresso 'Installed SDKs' pane which is located at the bottom.

LPCXpresso824-MAX Board has LPC824M201JHI33Y as tarrget application MCU. It also has onboard debugger using LPC11U35FHI33 as a bridge between the development computer and the debug access port. The firmware on the debugger is out of date, and we need to update the LPC11U35 debugger DAPLink firmware.

Note: Do not use the firmware from https://os.mbed.com/handbook/Firmware-LPCXpresso824-MAX

Instead, use the one from the following repository.

https://github.com/ARMmbed/DAPLink/releases/tag/v0254

After downloading the release package 0254_release_package_f499eb6e.zip, we need to use '0254_lpc11u35_lpc824xpresso_0x0000.bin' for our debugger.

To update the firmware, hold the reset button on the board and connect USB. It should appear as CPR DISABLED drive. Then, delete firmware.bin and copy the file '0254_lpc11u35_lpc824xpresso_0x0000.bin' onto the drive.

SDK Example

Let us start with MCUXpresso's SDK example 'led_blinky' using LPCXpresso824-MAX Board. Click 'Import SDK example(s)' in the lower left pane, choose LPCXpresso824-MAX Board SDK, and click next. Then choose 'led_blinky' and click 'Finish'.

The example blinks red LED using SysTick. I will rename the project as "LPC824_Tmr_Com" by clicking on the project and choose rename.

Software Timers

Software timers are easy to implement. I have developed sotware timer module called "ceTmr" as an simplified alternative to software timer provided by FreeRTOS. You first need to copy "ceTmr.h" and "ceTmr.c" into source folder. They are available at the following repository.

https://github.com/yan9a/lpc824/tree/main/LPC824_Tmr_Com/source

To use the software timer:
  • Include the header file ceTmr.h

    #include "ceTmr.h"
    


  • Set SysTick configuration to enable SysTick timer at desired interval

    // Set systick reload value to generate 1ms interrupt
    if (SysTick_Config(SystemCoreClock / 1000U)) { while (1) { } }
    


  • Define callback function to execute at timeout

    void sby_led_to(void){
    	GPIO_PortToggle(GPIO, BOARD_LED_PORT, 1u << BOARD_LED_PIN);
    }
    


  • Create the timer by calling "ceTmrCreate" with interval, setting argument for oneshot as false to use autoreload timer, and callback function for timeout.

    ceTmr_t* sbyLED = ceTmrCreate(500,false,sby_led_to);
    


  • Start the timer by calling "ceTmrStart".

    ceTmrStart(sbyLED); // start the standby led timer
    


  • And calling "ceTmrTask" in the main loop.

    while (1)
    {
        ceTmrTask();
    }
    


If you want to use other timer tick function instead of SysTick handler, you can modified the following line in ceTmr.h.

#define ceTmrTick SysTick_Handler // define timer tick function


The maximum number of timers can be defined there also.

#define CE_TMR_MAX_NUMBER 10 // maximum number of timers


The resulting main file is as follows.

#include "pin_mux.h"
#include "board.h"
#include "ceTmr.h"

#define BOARD_LED_PORT DEMO_LED_RED_PORT
#define BOARD_LED_PIN  DEMO_LED_RED_PIN

void sby_led_to(void){
	GPIO_PortToggle(GPIO, BOARD_LED_PORT, 1u << BOARD_LED_PIN);
}

int main(void)
{
  GPIO_PortInit(GPIO, BOARD_LED_PORT);
  BOARD_InitBootPins();
  BOARD_InitBootClocks();
  //-----------------------------------------------------------------------------
  // Init software timer
  // Set systick reload value to generate 1ms interrupt
  if (SysTick_Config(SystemCoreClock / 1000U)) { while (1) { } }
  // create timer with interval 500 ms, not oneshot, call back function 'sby_led_to'
  ceTmr_t* sbyLED = ceTmrCreate(500,false,sby_led_to);
  ceTmrStart(sbyLED); // start the standby led timer
  //-----------------------------------------------------------------------------
  while (1)
  {
    ceTmrTask();
  }
}


Com

Next thing I would like to discuss is using ring buffered UART communication module which I developed. It is called 'ceCom' and it provides functions to use all three UARTs - UART0 to UART2 - on LPC824 in non-blocking way. As an example, I will demonstrate using UART0 which is attached to OpenSDA USB com port on LPCXpresso824-MAX Board. For that, depending on the version of your hardware, you might need to resolder 0 ohm resistor on SJ9 jumper to connect pin 2-3 side.


Figure 1. Resoldering SJ9 to connect pin 2-3 (left) side.


Copy "ceCom.h" and "ceCom.c" into source folder. They are available at the following repository, the same one mentioned above.

https://github.com/yan9a/lpc824/tree/main/LPC824_Tmr_Com/source

To use ceCom:
  • Include the header file ceCom.h

    #include "ceCom.h"
    


  • Define callback function which will called everytime a character is received. The function name is ceComOnRx0 for UART0, ceComOnRx1 for UART1, etc. In this example, we will echo back the character.

    void ceComOnRx0(uint8_t b)
    {
    	ceComPutch(0,b);
    }
    


  • Initialize the module by calling "ceComInitialize". You can customized UART configuration such as pins, baud rate, etc. in ceCom.c.

      // Init UART
      ceComInitialize();
    


  • Transmitting can be performed by calling functions defined in ceCom.h such as ceComPrint with respective UART number.

    ceComPrint(0,"Hello\n");
    


  • And calling "ceComTask" in the main loop

    while (1)
    {
        ceComTask();
    }
    


The resulting main file implementing both ceTmr and ceCom is shown below.

#include "pin_mux.h"
#include "board.h"
#include "ceTmr.h"
#include "ceCom.h"

#define BOARD_LED_PORT 0U
#define BOARD_LED_PIN  12U

void sby_led_to(void){
	GPIO_PortToggle(GPIO, BOARD_LED_PORT, 1u << BOARD_LED_PIN);
}

void ceComOnRx0(uint8_t b)
{
	ceComPutch(0,b);
}

int main(void)
{
    GPIO_PortInit(GPIO, BOARD_LED_PORT);
    BOARD_InitPins();
    BOARD_BootClockIRC12M();
    // BOARD_InitDebugConsole();
    //-----------------------------------------------------------------------------
	// Init software timer
	// Set systick reload value to generate 1ms interrupt
	if (SysTick_Config(SystemCoreClock / 1000U)) { while (1) { } }
	// create timer with interval 500 ms, not oneshot, call back function 'sby_led_to'
	ceTmr_t* sbyLED = ceTmrCreate(500,false,sby_led_to);
	ceTmrStart(sbyLED); // start the standby led timer
	//-----------------------------------------------------------------------------
	ceComInitialize();// Init UART
	ceComPrint(0,"Hello\n");
	//-----------------------------------------------------------------------------
    while (1)
    {
    	ceTmrTask();
    	ceComTask();
    }
}


The purpose of this article is to provide simple, light weight, easy to implement timer and communication modules which can be easily modified to be used on similar MCUs.

Related Articles

[1] Cool Emerald. Flash content protection for LPC824. 2017 Jun 6.
url: http://cool-emerald.blogspot.com/2017/06/flash-content-protection-for-lpc824.html.



References

[1] Cool Emerald. Circular Buffered UART Com Module for 8051 Microcontroller. 2010 Jun 10.
url: http://cool-emerald.blogspot.com/2010/06/circular-buffered-uart-com-module-for.html.

[2] Cool Emerald. Software timers and Ring Buffered UART Com for Kinetis K82 MCU. 2021 July 5.
url: http://cool-emerald.blogspot.com/2021/07/software-timers-and-ring-buffered-uart.html.



No comments:

Post a Comment

Comments are moderated and don't be surprised if your comment does not appear promptly.