Building the STM32 Debug Output and Time System with Embedded Zorb Framework

1 Zorb Introduction
Zorb Framework is a lightweight embedded framework built on the principles of object-oriented programming.
The purpose of building the Zorb Framework is to enable rapid application development on chips that cannot run Linux, avoiding the need to reinvent the wheel repeatedly.
The initial design features of the Zorb Framework include:
  • Time system function zf_time
  • Circular buffer function zf_buffer
  • List function zf_list
  • State machine function zf_fsm
  • Event function zf_event
  • Timer function zf_timer
  • Task function zf_task
The first six functions can implement a purely event-driven program, which can basically meet the needs of developing medium and small embedded applications. Adding the task function is to meet the needs of some programs that require high real-time performance. Of course, the first six functions can also be trimmed and run on existing embedded systems, which can also meet real-time requirements.

2 Setting Up the Embedded Environment

Using the STM32F429 development board as the hardware running environment, the hardware resources used are Serial Port 1 and SysTick, where Serial Port 1 provides debugging print functionality, and SysTick provides system time counting functionality.
Building the STM32 Debug Output and Time System with Embedded Zorb Framework
There’s not much to say about setting up the hardware environment; you can refer to the examples provided by the development board to set it up. The board-level initialization has completed the initialization of the debug serial port and SysTick.
/****************************************************************************** * Description  : Hardware environment initialization * Parameters  : None * Returns  : None******************************************************************************/void BSP_init(void){    /* Select nested vector interrupt controller group */    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);    /* Initialize debug serial port */    Debug_USART_init();    /* SysTick initialization */    SystemTick_init();}/****************************************************************************** * Description  : Hardware low-level program * Parameters  : None * Returns  : None******************************************************************************/void BSP_process(void){}

3 Debug Output

When developing a program, the first and most important step is to set up the debugging environment. We use Serial Port 1 as the debug output (mapped to printf), and the debug information is divided into three levels. The upper computer can highlight prompts based on different levels:
/**  *****************************************************************************  * @file    zf_debug.h  * @author  Zorb  * @version V1.0.0  * @date    2018-06-28  * @brief   Header file for debug output  *****************************************************************************  * @history  *  * 1. Date:2018-06-28  *    Author:Zorb  *    Modification: Created the file  *  *****************************************************************************  */#ifndef __ZF_DEBUG_H__#define __ZF_DEBUG_H__#ifdef __cplusplusextern "C" {#endif#include "stdio.h"#include "stdbool.h"#define LOG_D 0; /* Information level: Normal */#define LOG_W 1; /* Information level: Warning */#define LOG_E 2; /* Information level: Error */#define _ZF_DEBUG             /* Define debug functionality */#define ZF_DEBUG_ON true      /* Enable debug functionality */#ifdef _ZF_DEBUG    #if ZF_DEBUG_ON        #define ZF_DEBUG(rank, x...) do     \
        {                                   \
            char code[10] = "[rank=0]";     \
            code[6] = '0' + (char)rank;     \
            if (code[6] != '0')             \
            {                               \
                printf("%s", code);         \
            }                               \
            printf(x);                      \
        } while(0)    #else        #define ZF_DEBUG(rank, x...)    #endif /* ZF_DEBUG_ON */#endif /* _ZF_DEBUG */#ifdef __cplusplus}#endif#endif /* __ZF_DEBUG_H__ */ /******************************** END OF FILE ********************************/

4 Implementing Assertions

During development, performing assertions in critical places can help locate bugs easily.
/**  *****************************************************************************  * @file    zf_assert.h  * @author  Zorb  * @version V1.0.0  * @date    2018-06-28  * @brief   Header file for assertions  *****************************************************************************  * @history  *  * 1. Date:2018-06-28  *    Author:Zorb  *    Modification: Created the file  *  *****************************************************************************  */#ifndef __ZF_ASSERT_H__#define __ZF_ASSERT_H__#ifdef __cplusplusextern "C" {#endif#include "stdint.h"#define _ZF_ASSERT              /* Define assertion functionality */#define ZF_ASSERT_ON true       /* Enable assertion functionality */#ifdef _ZF_ASSERT    #if ZF_ASSERT_ON         #define ZF_ASSERT(expression_) ((expression_) ?\n            (void)0 : ZF_assertHandle((uint8_t *)__FILE__, (int)__LINE__));    #else         #define ZF_ASSERT(expression_)    #endif /* ZF_ASSERT_ON */#endif /* _ZF_ASSERT *//* Handling when an assertion occurs */void ZF_assertHandle(uint8_t *pFileName, int line);#ifdef __cplusplus}#endif#endif /* __ZF_ASSERT_H__ */ /******************************** END OF FILE ********************************/
The handling of assertions is simple; it just tells us which file and line has an error, implemented as follows:
/**  *****************************************************************************  * @file    zf_assert.c  * @author  Zorb  * @version V1.0.0  * @date    2018-06-28  * @brief   Implementation of assertions  *****************************************************************************  * @history  *  * 1. Date:2018-06-28  *    Author:Zorb  *    Modification: Created the file  *  *****************************************************************************  */#include "zf_assert.h"#include "zf_debug.h"/****************************************************************************** * Description  : Handling when an assertion occurs * Parameters  : (in)-pFileName File name *         (in)-line Line number * Returns  : None******************************************************************************/void ZF_assertHandle(uint8_t *pFileName, int line){    ZF_DEBUG(LOG_E, "file:%s line:%d:asserted\r\n", pFileName, line);    while (1);}/******************************** END OF FILE ********************************/

5 Establishing a Time System

To reduce the framework’s resource consumption, the minimum time cycle of the framework is initially set to 1ms. Therefore, we need to set the SysTick timing period to 1ms, and then each time we enter the interrupt, we can count for our framework.
/****************************************************************************** * Description  : SysTick interrupt service routine * Parameters  : None * Returns  : None******************************************************************************/void SysTick_Handler(void){    /* Provide timing for zorb framework */    ZF_timeTick();}
Currently, the functionality provided by the time system is quite basic, with only system tick counting and system blocking delay. We will expand the time system when developing the timer and task functionalities later.
/**  *****************************************************************************  * @file    zf_time.h  * @author  Zorb  * @version V1.0.0  * @date    2018-06-28  * @brief   Header file for system time  *****************************************************************************  * @history  *  * 1. Date:2018-06-28  *    Author:Zorb  *    Modification: Created the file  *  *****************************************************************************  */#ifndef __ZF_TIME_H__#define __ZF_TIME_H__#ifdef __cplusplusextern "C" {#endif#include "stdbool.h"#include "stdint.h"/* System tick period (ms) */#define ZF_TICK_PERIOD 1/* Get system tick count */#define ZF_SYSTICK() ZF_getSystemTick()/* Get system time (ms) */#define ZF_SYSTIME_MS() ZF_getSystemTimeMS()/* System delay (ms) */#define ZF_DELAY_MS(ms_) do                            \{                                                      \    if (ms_ % ZF_TICK_PERIOD)                          \    {                                                  \        ZF_delayTick((ms_ / ZF_TICK_PERIOD) + 1);      \    }                                                  \    else                                               \    {                                                  \        ZF_delayTick(ms_ / ZF_TICK_PERIOD);            \    }                                                  \} while(0)/* Get system tick count */uint32_t ZF_getSystemTick(void);/* Get system time (ms) */uint32_t ZF_getSystemTimeMS(void);/* System delay */void ZF_delayTick(uint32_t tick);/* System tick program (needs to be hung in hardware time interrupt) */void ZF_timeTick (void);#ifdef __cplusplus}#endif#endif /* __ZF_TIME_H__ */ /******************************** END OF FILE ********************************/

6 Conclusion

The functionalities implemented in this article are quite basic, but they are the foundation for the development of the entire framework. A well-established debugging output environment can help us quickly locate bugs, thereby improving development efficiency.

Zorb Framework GitHub:https://github.com/54zorb/Zorb-Framework

[Paid] STM32 Embedded Material Package

Leave a Comment

×