LPC1100 系列单片机_10.调试与测试方法

10. 调试与测试方法

10.1 引言

在嵌入式系统开发中,调试与测试是确保系统稳定性和可靠性的关键步骤。LPC1100 系列单片机基于 ARM Cortex-M0 核心,提供了多种调试和测试工具,以帮助开发者识别和解决问题。本节将详细介绍 LPC1100 系列的调试与测试方法,包括硬件调试接口、软件调试工具、单元测试和系统测试等方面。
在这里插入图片描述

10.2 硬件调试接口

LPC1100 系列单片机支持多种硬件调试接口,包括 JTAG 和 SWD(Serial Wire Debug)。这些接口允许开发者通过调试工具连接到单片机,进行断点设置、单步执行、内存查看和修改等操作。

10.2.1 JTAG 接口

JTAG(Joint Test Action Group)接口是一种标准的调试接口,广泛用于嵌入式系统中。LPC1100 系列单片机通常有 4 个 JTAG 引脚:TMS、TCK、TDI 和 TDO。

  • TMS(Test Mode Select): 用于选择 JTAG 状态机的不同状态。
  • TCK(Test Clock): 用于同步 JTAG 操作的时钟信号。
  • TDI(Test Data In): 用于输入测试数据。
  • TDO(Test Data Out): 用于输出测试数据。

10.2.2 SWD 接口

SWD(Serial Wire Debug)接口是一种更简单的调试接口,适用于 ARM Cortex-M0 核心。LPC1100 系列单片机通常有 2 个 SWD 引脚:SWDIO 和 SWCLK。

  • SWDIO(Serial Wire Debug I/O): 用于双向数据传输。
  • SWCLK(Serial Wire Debug Clock): 用于同步数据传输的时钟信号。

10.2.3 调试适配器

为了连接调试接口,需要使用调试适配器。常用的调试适配器包括:

  • LPC-Link2: NXP 官方提供的调试适配器,支持 JTAG 和 SWD 接口。
  • Segger J-Link: 第三方提供的高性能调试适配器,支持多种 ARM 核心。
  • OpenOCD: 开源的调试适配器软件,支持多种调试硬件。

10.2.4 示例:使用 LPC-Link2 进行调试

// LPC-Link2 连接示例
// 硬件连接:将 LPC-Link2 的 SWD 接口连接到 LPC1100 的 SWD 引脚
// 软件配置:使用 Keil MDK 或 IAR Embedded Workbench 配置调试适配器

// 1. 在 Keil MDK 中配置 LPC-Link2
// 打开项目设置 -> Debug -> Settings
// 选择 "LPC-Link2" 作为调试适配器
// 选择 "SWD" 作为调试接口

// 2. 在 IAR Embedded Workbench 中配置 LPC-Link2
// 打开项目选项 -> Debugger -> Setup
// 选择 "LPC-Link2" 作为调试适配器
// 选择 "SWD" 作为调试接口

10.3 软件调试工具

10.3.1 Keil MDK

Keil MDK(Microcontroller Development Kit)是一款常用的 ARM 单片机开发工具,提供了集成的调试环境。

10.3.1.1 断点设置

在 Keil MDK 中,可以通过以下方法设置断点:

  • 源代码断点: 在代码行前点击鼠标左键,或使用快捷键 F9
  • 数据断点: 在变量声明处或变量使用处设置断点,观察变量的值变化。
// 示例:在源代码中设置断点
void main(void) {
    // 初始化硬件
    SystemInit();

    // 设置源代码断点
    int count = 0;  // 在这里设置断点

    while (1) {
        // 执行任务
        count++;
        if (count > 100) {
            count = 0;
        }
    }
}
10.3.1.2 单步执行

在 Keil MDK 中,可以通过以下快捷键进行单步执行:

  • F10: 单步执行,不进入函数。
  • F11: 单步执行,进入函数。
10.3.1.3 内存查看与修改

在 Keil MDK 中,可以使用 Memory 视图查看和修改内存内容。

// 示例:查看特定地址的内存内容
// 打开 Memory 视图
// 输入地址:0x20000000
// 查看和修改该地址的内存内容

10.3.2 IAR Embedded Workbench

IAR Embedded Workbench 是另一款常用的 ARM 单片机开发工具,提供了强大的调试功能。

10.3.2.1 断点设置

在 IAR Embedded Workbench 中,可以通过以下方法设置断点:

  • 源代码断点: 在代码行前点击鼠标左键,或使用快捷键 F9
  • 数据断点: 在变量声明处或变量使用处设置断点,观察变量的值变化。
// 示例:在源代码中设置断点
void main(void) {
    // 初始化硬件
    SystemInit();

    // 设置源代码断点
    int count = 0;  // 在这里设置断点

    while (1) {
        // 执行任务
        count++;
        if (count > 100) {
            count = 0;
        }
    }
}
10.3.2.2 单步执行

在 IAR Embedded Workbench 中,可以通过以下快捷键进行单步执行:

  • F10: 单步执行,不进入函数。
  • F11: 单步执行,进入函数。
10.3.2.3 内存查看与修改

在 IAR Embedded Workbench 中,可以使用 Memory 视图查看和修改内存内容。

// 示例:查看特定地址的内存内容
// 打开 Memory 视图
// 输入地址:0x20000000
// 查看和修改该地址的内存内容

10.3.3 OpenOCD

OpenOCD 是一款开源的调试工具,支持多种调试硬件和接口。可以通过命令行或集成在开发环境中使用。

10.3.3.1 配置 OpenOCD

在使用 OpenOCD 之前,需要配置调试适配器和目标设备。

# 配置文件示例:lpc1100.cfg
source [find interface/lpc-link2.cfg]
source [find target/lpc1100.cfg]
10.3.3.2 启动调试

通过命令行启动 OpenOCD,并连接到调试适配器。

# 启动 OpenOCD
openocd -f lpc1100.cfg
10.3.3.3 使用 GDB 进行调试

可以使用 GDB(GNU Debugger)连接到 OpenOCD 进行调试。

# 启动 GDB
arm-none-eabi-gdb

# 连接到 OpenOCD
(gdb) target extended-remote :3333

# 设置断点
(gdb) break main

# 运行程序
(gdb) continue

10.4 单元测试

单元测试是测试软件模块或函数的一种方法,确保每个模块在集成之前都能正常工作。LPC1100 系列单片机支持多种单元测试框架,如 CMocka 和 Unity。

10.4.1 CMocka

CMocka 是一个用于 C 语言的单元测试框架,支持复杂的测试场景。

10.4.1.1 安装 CMocka
# 安装 CMocka
sudo apt-get install libcmocka0 libcmocka-dev
10.4.1.2 编写测试用例
// 示例:测试一个简单的函数
#include <cmocka.h>

// 被测试的函数
int add(int a, int b) {
    return a + b;
}

// 测试用例
static void test_add(void **state) {
    (void) state; // unused
    assert_int_equal(add(1, 2), 3);
    assert_int_equal(add(0, 0), 0);
    assert_int_equal(add(-1, 1), 0);
}

// 测试套件
int main(void) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(test_add),
    };
    return cmocka_run_group_tests(tests, NULL, NULL);
}

10.4.2 Unity

Unity 是一个轻量级的单元测试框架,适用于嵌入式系统。

10.4.2.1 安装 Unity
# 下载 Unity 源代码
git clone https://github.com/ThrowTheSwitch/Unity.git

# 将 Unity 源代码添加到项目中
10.4.2.2 编写测试用例
// 示例:测试一个简单的函数
#include "unity.h"

// 被测试的函数
int add(int a, int b) {
    return a + b;
}

// 测试用例
void test_add(void) {
    TEST_ASSERT_EQUAL_INT(3, add(1, 2));
    TEST_ASSERT_EQUAL_INT(0, add(0, 0));
    TEST_ASSERT_EQUAL_INT(0, add(-1, 1));
}

// 测试套件
int main(void) {
    UNITY_BEGIN();
    RUN_TEST(test_add);
    return UNITY_END();
}

10.5 系统测试

系统测试是在整个系统集成之后进行的测试,确保所有模块协同工作正常。LPC1100 系列单片机支持多种系统测试方法,如使用串口输出日志、使用 LED 指示灯等。

10.5.1 串口输出日志

通过串口输出日志是一种常用的系统测试方法,可以在运行时查看系统的状态和输出。

10.5.1.1 初始化串口
// 串口初始化示例
#include "LPC11xx.h"

void UART_Init(void) {
    // 配置 UART 时钟
    LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 12);  // 使能 UART 时钟

    // 配置 UART 引脚
    LPC_IOCON->P0_0 |= (1 << 0);  // P0.0 为 UART TX
    LPC_IOCON->P0_1 |= (1 << 0);  // P0.1 为 UART RX

    // 配置 UART 波特率
    LPC_USART->LCR = 0x83;  // 8 位数据,1 位停止,无奇偶校验
    LPC_USART->DLL = 24;    // 设置波特率
    LPC_USART->DLM = 0;     // 设置波特率
    LPC_USART->FDR = 0x11;  // 设置波特率
    LPC_USART->LCR = 0x03;  // 8 位数据,1 位停止,无奇偶校验

    // 使能 UART 传输
    LPC_USART->IER = 1;  // 使能 RX 中断
    LPC_USART->FCR = 0x07;  // 使能 FIFO,复位 FIFO,设置触发阈值
}

// 串口发送字符
void UART_SendChar(char data) {
    while (!(LPC_USART->LSR & 0x20));  // 等待发送缓冲区为空
    LPC_USART->THR = data;  // 发送数据
}

// 串口发送字符串
void UART_SendString(const char *str) {
    while (*str) {
        UART_SendChar(*str++);
    }
}
10.5.1.2 使用串口输出日志
// 示例:在主函数中使用串口输出日志
void main(void) {
    // 初始化硬件
    SystemInit();
    UART_Init();

    // 输出日志
    UART_SendString("System initialized\n");

    int count = 0;
    while (1) {
        // 执行任务
        count++;
        if (count > 100) {
            count = 0;
            UART_SendString("Count reset to 0\n");
        }
    }
}

10.5.2 使用 LED 指示灯

LED 指示灯是一种直观的系统测试方法,可以用来显示系统的状态。

10.5.2.1 初始化 LED
// LED 初始化示例
#include "LPC11xx.h"

void LED_Init(void) {
    // 配置 LED 引脚
    LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 9);  // 使能 GPIO 时钟
    LPC_GPIO->DIR |= (1 << 17);  // P1.17 为输出
}

// LED 点亮
void LED_On(void) {
    LPC_GPIO->DATA |= (1 << 17);  // P1.17 点亮
}

// LED 熄灭
void LED_Off(void) {
    LPC_GPIO->DATA &= ~(1 << 17);  // P1.17 熄灭
}
10.5.2.2 使用 LED 指示系统状态
// 示例:在主函数中使用 LED 指示系统状态
void main(void) {
    // 初始化硬件
    SystemInit();
    LED_Init();

    int count = 0;
    while (1) {
        // 执行任务
        count++;
        if (count > 100) {
            count = 0;
            LED_On();
            for (int i = 0; i < 100000; i++) {
                __NOP();  // 延时
            }
            LED_Off();
        }
    }
}

10.6 性能测试

性能测试是评估系统运行效率和资源使用情况的一种方法。LPC1100 系列单片机可以通过定时器和性能分析工具进行性能测试。

10.6.1 定时器

LPC1100 系列单片机内置多个定时器,可以用来测量函数的执行时间。

10.6.1.1 初始化定时器
// 定时器初始化示例
#include "LPC11xx.h"

void Timer_Init(void) {
    // 使能定时器时钟
    LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 0);  // 使能 Timer 0 时钟

    // 配置定时器
    LPC_TMR32B0->CTCR = 0x00;  // 选择上升沿计数
    LPC_TMR32B0->PR = 0x00;    // 预分频值为 0
    LPC_TMR32B0->TCR = 0x02;   // 复位定时器
    LPC_TMR32B0->TCR = 0x01;   // 使能定时器
}
10.6.1.2 测量函数执行时间
// 测量函数执行时间示例
#include "LPC11xx.h"

void Timer_Start(void) {
    LPC_TMR32B0->TCR = 0x02;  // 复位定时器
    LPC_TMR32B0->TCR = 0x01;  // 使能定时器
}

uint32_t Timer_Stop(void) {
    LPC_TMR32B0->TCR = 0x00;  // 停止定时器
    return LPC_TMR32B0->TC;   // 获取计数值
}

void test_function(void) {
    // 模拟一个耗时的操作
    for (int i = 0; i < 1000000; i++) {
        __NOP();  // 延时
    }
}

int main(void) {
    // 初始化硬件
    SystemInit();
    UART_Init();
    Timer_Init();

    // 测量函数执行时间
    Timer_Start();
    test_function();
    uint32_t elapsed_time = Timer_Stop();

    // 输出结果
    UART_SendString("Elapsed time: ");
    UART_SendString(itoa(elapsed_time));
    UART_SendString(" ticks\n");

    while (1) {
        // 运行其他任务
    }
}

10.6.2 性能分析工具

使用性能分析工具(如 IAR Embedded Workbench 的 C-SPY)可以更详细地分析系统的性能。

10.6.2.1 配置 C-SPY

在 IAR Embedded Workbench 中,可以通过以下步骤配置 C-SPY 性能分析工具:

  1. 打开项目选项 -> Debugger -> Setup
  2. 选择 “Performance Analysis” 选项卡
  3. 配置性能分析参数
10.6.2.2 使用 C-SPY 进行性能分析
// 示例:使用 C-SPY 进行性能分析
#include "LPC11xx.h"

void test_function(void) {
    // 模拟一个耗时的操作
    for (int i = 0; i < 1000000; i++) {
        __NOP();  // 延时
    }
}

int main(void) {
    // 初始化硬件
    SystemInit();

    // 测量函数执行时间
    // 使用 C-SPY 的性能分析功能
    __iar_profile_start();  // 开始性能分析
    test_function();
    __iar_profile_stop();   // 停止性能分析

    while (1) {
        // 运行其他任务
    }
}

10.6.3 使用 Keil MDK 的性能分析工具

Keil MDK 也提供了一套强大的性能分析工具,可以用来分析程序的执行时间和内存使用情况。

10.6.3.1 配置性能分析工具

在 Keil MDK 中,可以通过以下步骤配置性能分析工具:

  1. 打开项目设置 -> Debug -> Settings
  2. 选择 “Profiler” 选项卡
  3. 配置性能分析参数
10.6.3.2 使用性能分析工具进行分析
// 示例:使用 Keil MDK 的性能分析工具
#include "LPC11xx.h"

void test_function(void) {
    // 模拟一个耗时的操作
    for (int i = 0; i < 1000000; i++) {
        __NOP();  // 延时
    }
}

int main(void) {
    // 初始化硬件
    SystemInit();

    // 测量函数执行时间
    // 使用 Keil MDK 的性能分析功能
    __CPROFILER_START();  // 开始性能分析
    test_function();
    __CPROFILER_STOP();   // 停止性能分析

    while (1) {
        // 运行其他任务
    }
}

10.7 调试技巧

在调试过程中,掌握一些调试技巧可以显著提高效率和准确性。以下是一些常用的调试技巧:

10.7.1 使用条件断点

条件断点允许在满足特定条件时暂停程序执行,这对于调试循环或条件分支非常有用。

10.7.1.1 在 Keil MDK 中设置条件断点
  1. 在代码行前点击鼠标右键
  2. 选择 “Breakpoint” -> “Condition”
  3. 输入条件表达式
// 示例:在 Keil MDK 中设置条件断点
void main(void) {
    // 初始化硬件
    SystemInit();
    UART_Init();

    int count = 0;
    while (1) {
        // 执行任务
        count++;
        if (count > 100) {
            count = 0;
            UART_SendString("Count reset to 0\n");
        }
    }
}
10.7.1.2 在 IAR Embedded Workbench 中设置条件断点
  1. 在代码行前点击鼠标右键
  2. 选择 “Breakpoint” -> “Condition”
  3. 输入条件表达式

10.7.2 使用日志记录

通过在代码中添加日志记录,可以在运行时查看关键变量的值和程序的执行流程。

10.7.2.1 在代码中添加日志记录
// 示例:在代码中添加日志记录
void main(void) {
    // 初始化硬件
    SystemInit();
    UART_Init();

    int count = 0;
    while (1) {
        // 执行任务
        count++;
        UART_SendString("Count: ");
        UART_SendString(itoa(count));
        UART_SendString("\n");

        if (count > 100) {
            count = 0;
            UART_SendString("Count reset to 0\n");
        }
    }
}

10.7.3 使用实时数据查看

实时数据查看功能允许开发者在运行时查看变量的值,这对于调试动态变化的系统非常有用。

10.7.3.1 在 Keil MDK 中使用实时数据查看
  1. 打开 “Watch” 视图
  2. 添加需要查看的变量
10.7.3.2 在 IAR Embedded Workbench 中使用实时数据查看
  1. 打开 “Watch” 视图
  2. 添加需要查看的变量

10.7.4 使用硬件断点

硬件断点利用单片机内部的硬件资源,可以更精确地控制断点位置。

10.7.4.1 在 Keil MDK 中设置硬件断点
  1. 在代码行前点击鼠标右键
  2. 选择 “Breakpoint” -> “Hardware Breakpoint”
10.7.4.2 在 IAR Embedded Workbench 中设置硬件断点
  1. 在代码行前点击鼠标右键
  2. 选择 “Breakpoint” -> “Hardware Breakpoint”

10.8 结论

调试与测试是嵌入式系统开发中不可或缺的环节。LPC1100 系列单片机提供了多种硬件和软件工具,帮助开发者高效地进行调试和测试。通过合理的使用这些工具和技巧,可以显著提高系统的稳定性和可靠性。希望本节的内容对您的开发工作有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值