zoukankan      html  css  js  c++  java
  • Arduino平台基于DbC的软件调试

    基于LED和串口通信的DBC调试工具:HAssert --- Hyper LED/Serial Assert 。

    本文基于DbC思想 ,在Arduino平台上实现了两种断言显示方式---LED显示和串口输出显示。
    LED显示方式
    适用于没有串口(这种情况很少),或者串口已经被占用的情况,只用一个LED的显示次数来调试程序;
    串口输出显示方式
    可以把断言内容传送到PC机,在PC机看到出错的位置(文件名和行号)。
    以下的HAssert.h和HAssert.cpp实现了DbC调试的断言。

    一.HAssert.h头文件

    #ifndef H_ASSERT_H
    #define H_ASSERT_H
    #include <stdint.h>                 // C99-standard exact-width integers
    #include <avr/pgmspace.h>
    //#define ROM_BYTE(rom_var_)    pgm_read_byte_near(&(rom_var_))
    //#define ROM   PROGMEM
    /// 1.有/无断言选择开关(配置1)
    // (1)调试时,   H_ASSERT = 1,断言有效
    // (2)发布软件时,H_ASSERT = 0,自动去掉代码中插入的所有断言
    #define H_ASSERT_EN  1
    ///2.LED/串口显示断言选择开关(配置2)
    //(1)H_LED_ASSERT_EN = 1时,选择LED显示断言
    //(2)H_LED_ASSERT_EN = 0时,选择串口显示断言
    #define H_LED_ASSERT_EN   0
    //=================================================
    /// 状态LED引脚 (配置3)
    #define H_ASSERT_LED_PIN    13 //Arduino板用13; MSR和SWT板用RxErr状态LED,7.
    /// 状态LED延时时间(配置4)
    // (1)仿真用了10000ms, 实际上可以修改成1秒的时间
    #define H_ASSERT_LED_DELAY_TIME    1000 // ms
    //================================================
    ///3.H_ASSERT_EN == 0,去掉断言宏
    #if  H_ASSERT_EN == 0
        #define H_ASSERT_ID(id, test)
        #define H_REQUIRE_ID(id, test)
        #define H_ERROR_ID(id)
        #define H_BREAKPOINT_ID(id)
        #define H_DEFINE_THIS_FILE
        #define H_DEFINE_THIS_MODULE(name_)
        #define H_ASSERT(test)
        #define H_REQUIRE(test)
        #define H_ERROR()
        #define H_BREAK_POINT()
    ///4.H_ASSERT_EN == 1,加入断言宏
    #else
        ///4.0.声明断言函数
        #ifdef __cplusplus
            extern "C" {
        #endif
            void H_onAssert_id(uint8_t id); //LED显示断言回调函数声明
            void H_onAssert(char const PROGMEM * const file, int line); //串口显示断言回调函数声明
        #ifdef __cplusplus
            }
        #endif
        ///4.1.LED断言宏
        #if H_LED_ASSERT_EN == 1
            ///LED断言---带id参数
            //(1).id参数可以指示错误分类等,如用LED闪亮的次数分类
            //(2). 建议id = 2~255, id=0和1都算做1次,以下类同
            ///断言宏
            #define H_ASSERT_ID(id, test)     if (test) { 
                                         } 
                                            else (H_onAssert_id((id)))
            ///必要条件
            #define H_REQUIRE_ID(id, test)   H_ASSERT_ID(id, test)
            ///错误
            #define H_ERROR_ID(id)           (H_onAssert_id((id)))
            ///断点
            #define H_BREAKPOINT_ID(id)      (H_onAssert_id((id)))
        ///4.2.串口断言宏
        #else
            ///加入到每个文件的#include "HSAssert.h"之后,文件的前边。
            //绝对路径文件,太长!
            #define H_DEFINE_THIS_FILE 
                static char const PROGMEM l_file[] = __FILE__;
            ///自己写文件名,或模块名
            #define H_DEFINE_THIS_MODULE(module_name_) 
                static char const PROGMEM l_file[] = #module_name_;
            ///断言宏
            #define H_ASSERT(test)     if (test) {
                                        } 
                                    else (H_onAssert(l_file, __LINE__))
            ///必要条件
            #define H_REQUIRE(test)  H_ASSERT(test)
            ///错误
            #define H_ERROR()       (H_onAssert(l_file, __LINE__))
            ///断点 停止
            #define H_BREAKPOINT()      { Serial.print("--- Breakpoint --- ");
                                          (H_onAssert(l_file, __LINE__)); 
                                          cli();
                                          while(1);
                                        } while(0)
        #endif
    #endif
    #endif       
    

    二.HAssert.cpp文件

    #include <Arduino.h> 
    #include "HAssert.h"
    ///1.LED断言函数实现---显示闪亮次数 
    //(1).用一个LED亮表示有错,闪亮次数表示错误类型
    //(2).有代码中不同的位置放id不同的断言宏,用闪亮的次数表示错误类型
    //(3).建议id = 2~255,不建议用0和1.
    //(4).有错误就会停止
    void H_onAssert_id(uint8_t id) {
        pinMode(H_ASSERT_LED_PIN, OUTPUT);
        sei();
        delay(H_ASSERT_LED_DELAY_TIME);     
        for (uint8_t i = 0; i < id; i++) {
            digitalWrite(H_ASSERT_LED_PIN, LOW);
            delay(H_ASSERT_LED_DELAY_TIME);
            digitalWrite(H_ASSERT_LED_PIN, HIGH);
            delay(H_ASSERT_LED_DELAY_TIME);        
        }
        cli();
        while(1) { ; }  //停止,断言不会返回,错误就得处理掉!
        //asm volatile ("jmp 0x0000");    // 复位
    }
    ///2.串行断言函数实现---显示文件和出错行
    //只有H_BREAKPOINT()会停止
    void H_onAssert(char const PROGMEM * const file, int line) {
        int i =0 ;  
        char ch, buffer[60];      
        do {
            ch = (char)pgm_read_word(file + i);
            buffer[i++] = ch;
        } while((ch != 0)&&(i < 60) );
        Serial.print(line - 3,DEC); Serial.print(" Line Error in "); 
        Serial.print(buffer); Serial.println(" file.");    
    }
    

    三.DbC测试程序

    1.利用LED的DbC测试

    //////////////////////////////////////////////////////////////////////////////
    // 名称:利用LED的DbC测试
    //////////////////////////////////////////////////////////////////////////////
    ///LED断言要求:HAssert.h中
    //配置1:H_ASSERT_EN = 1
    //配置2:H_LED_ASSERT_EN = 1
    #include "HAssert.h"
    void setup() {
    }
    void loop() {
        uint8_t x = 5;
        uint8_t y = 6;
        H_REQUIRE_ID(2,x==y); //判断逻辑错误时,闪亮2次,最后保持亮
        H_REQUIRE_ID(3,x != y); //判断逻辑正确时,不亮
    H_ERROR_ID(10); //闪亮10次,最后保持亮
        H_BREAKPOINT_ID(10);//与 H_ERROR_ID(10)一样
    
        delay(100);
        while(1);
    }
    

    2.利用串口通信的DbC测试

     //////////////////////////////////////////////////////////////////////////////
    // 名称:利用串口通信的DbC测试
    //////////////////////////////////////////////////////////////////////////////
    ///串口断言要求:HAssert.h中
    //配置1:H_ASSERT_EN = 1
    //配置2:H_LED_ASSERT_EN = 0
    #include "HAssert.h"
    #include <Arduino.h>
    H_DEFINE_THIS_MODULE("Test_HAssert.ino") //自己写文件名
    //HS_DEFINE_THIS_FILE  //绝对路径文件,太长!不用
    void setup() {
        Serial.begin(9600);
    }
    void loop() {
        uint8_t x = 5;
        uint8_t y = 6;
        H_ASSERT(false);
        H_REQUIRE(x == y);
        H_REQUIRE(x != y); //满足条件,不输出
        H_ERROR();
         H_BREAKPOINT();
        delay(100);
        //while(1);
    }
    

    四.串口通信DbC测试效果

    0a8cf9039245d6883507a700a4c27d1ed31b24fa

    本文中只给出串口DbC测试的运行效果,LED的DbC测试是在Arduino板上用LED闪亮次数来表示出错的位置。

  • 相关阅读:
    构建之法阅读笔记04
    构建之法阅读笔记03
    关于博客园的一些建议
    书的价钱
    找水王续
    《用户故事与敏捷开发》阅读笔记04
    每周学习进度——第六周
    每周学习进度——第五周
    《用户故事与敏捷开发》阅读笔记03
    软件需求与分析课堂讨论一
  • 原文地址:https://www.cnblogs.com/hyper99/p/Arduino-ping-tai-ji-yuDbC-de-ruan-jian-diao-shi.html
Copyright © 2011-2022 走看看