Создание заводской тестовой структуры для API низкого уровня ECU в системах HIL на основе CAN

Создание заводской тестовой структуры для API низкого уровня ECU в системах HIL на основе CAN

4 августа 2025 г.

Современные автомобильные системы полагаются на сложные электронные управления (ECU), чтобы управлять ряд функциональных возможностей. Обеспечение надежности и правильности этих систем требует надежных стратегий тестирования на уровне прошивки, особенно для водителей низкого уровня. В этой статье объясняется, как построить заводской тестовой код (FTC) для проверки программных API-интерфейсов низкого уровня в среде сети контроллера (CAN) с акцентом на системы аппаратного обеспечения в петле (HIL).

Мы пройдемся по практическим примерам кода C, изучим, как структурировать общение для операций GET/SET, и объясним, как моделировать операции памяти и диагностику. В то время как реальные ECU используют конфиденциальные модули, мы будем использовать примеры модулей, таких как PWM -контроллер, частотный модулятор и двигатель для демонстрации ключевых идей.


1. Обзор тестирования ECU и HIL

ЭКУ служат электронным мозгом подсистем, такими как рулевое управление, управление двигателями или электронное торможение. Каждый ECU взаимодействует с датчиками и приводами через драйверы, внедренные в прошивке низкого уровня. Тестирование этих драйверов гарантирует, что интеграция аппаратной программы является звуковой.

Тестирование HIL (оборудование-в-петли) вводит моделирование в реальном времени в цикл разработки, позволяя разработчикам тестировать ECU против виртуальных сред до физического развертывания. FTC обеспечивает автоматическое и целевое тестирование функций на уровне драйверов с помощью сообщений CAN.


2. Пример модулей

Для демонстрации мы смоделируем следующие модули:

  • ШИМ -контроллер- Управление выходами модуляции ширины импульса.
  • Частотный модулятор- Регулирует частоту сигнала.
  • Двигатель- Совместно имитирует интерфейс двигателя с управлением направлением и скоростью.

Каждый модуль предоставляет API, такие как:

  • set_pwm(channel, duty_cycle)
  • get_pwm(channel)
  • set_freq(channel, freq)
  • get_freq(channel)
  • read_diag(channel)

3. Can Can Design для FTC

Чтобы проверить эти модули, мы разрабатываем протокол CAN с выделенными идентификаторами сообщений для различных операций:

Операция

Can Id (Hex)

Set_pwm

0x101

Get_pwm

0x102

Set_freq

0x103

Get_freq

0x104

Read_diag

0x105

Read_mem

0x106

Write_mem

0x107

Мы также используем отдельные идентификаторы CAN для TX и RX:

  • TX Frame: Отправлено из тестового хоста в ECU.
  • RX рамка: Ответ от ECU.

Каждая кадра включает в себя:

  • Байт 0: идентификатор команды
  • Байт 1: идентификатор канала
  • Байты 2–5: полезная нагрузка (если есть)
  • Байт 6–7: CRC или зарезервированный

4. API-интерфейс низкого уровня в C

Давайте определим простые драйверные интерфейсы.

// pwm_controller.h
#ifndef PWM_CONTROLLER_H
#define PWM_CONTROLLER_H

void set_pwm(uint8_t channel, uint8_t duty_cycle);
uint8_t get_pwm(uint8_t channel);

#endif
// pwm_controller.c
#include "pwm_controller.h"

static uint8_t pwm_duty[8];

void set_pwm(uint8_t channel, uint8_t duty_cycle) {
    if (channel < 8) pwm_duty[channel] = duty_cycle;
}

uint8_t get_pwm(uint8_t channel) {
    return (channel < 8) ? pwm_duty[channel] : 0;
}
// frequency_modulator.h
#ifndef FREQ_MODULATOR_H
#define FREQ_MODULATOR_H

void set_freq(uint8_t channel, uint16_t freq);
uint16_t get_freq(uint8_t channel);

#endif
// frequency_modulator.c
#include "frequency_modulator.h"

static uint16_t freq_val[8];

void set_freq(uint8_t channel, uint16_t freq) {
    if (channel < 8) freq_val[channel] = freq;
}

uint16_t get_freq(uint8_t channel) {
    return (channel < 8) ? freq_val[channel] : 0;
}

5. Реализация тестового кода завода (FTC)

FTC анализируется входящие сообщения CAN, вызывает соответствующий API и отвечает с результатами.

// ftc_handler.c
#include "pwm_controller.h"
#include "frequency_modulator.h"
#include "can.h"

void process_can_frame(CanMessage *msg) {
    uint8_t command = msg->data[0];
    uint8_t channel = msg->data[1];
    uint32_t value = (msg->data[2] << 24) | (msg->data[3] << 16) |
                     (msg->data[4] << 8)  | msg->data[5];

    CanMessage tx_msg = {0};
    tx_msg.id = msg->id + 0x80; // response ID

    switch (command) {
        case 0x01: // SET_PWM
            set_pwm(channel, (uint8_t)value);
            break;
        case 0x02: // GET_PWM
            tx_msg.data[0] = get_pwm(channel);
            break;
        case 0x03: // SET_FREQ
            set_freq(channel, (uint16_t)value);
            break;
        case 0x04: // GET_FREQ
            {
                uint16_t freq = get_freq(channel);
                tx_msg.data[0] = (freq >> 8) & 0xFF;
                tx_msg.data[1] = freq & 0xFF;
            }
            break;
        case 0x05: // READ_DIAG (mocked)
            tx_msg.data[0] = 0xAA; // example diag result
            break;
        default:
            tx_msg.data[0] = 0xFF; // unknown command
            break;
    }

    send_can_message(&tx_msg);
}

Этот обработчик поддерживает динамическое тестирование с помощью инструментов CAN или сценариев Python.


6. Может ли инфраструктура связи

Предположим, что простая абстракция может:

// can.h
#ifndef CAN_H
#define CAN_H

typedef struct {
    uint32_t id;
    uint8_t data[8];
    uint8_t dlc;
} CanMessage;

void send_can_message(CanMessage *msg);
void receive_can_message(CanMessage *msg);

#endif

7. Hil Testing Flow

  1. Загрузите прошивку с FTC в ECU в HIL STACKE
  2. Подключить интерфейс (PCAN, VECTOR или NI-CAN)
  3. Отправить тестовые примеры с помощью сценариев Python или CAPL
  4. Наблюдайте за ответами и проходом log/Fail

Пример тестового примера Python:

import can

bus = can.interface.Bus(channel='can0', bustype='socketcan')
msg = can.Message(arbitration_id=0x101, data=[0x01, 0x02, 0x32, 0, 0, 0, 0, 0], is_extended_id=False)
bus.send(msg)

8. Моделирование чтения/записи памяти

Используйте выделенные команды для моделирования чтения и записи во внутренней памяти:

uint8_t memory_space[256];

void handle_mem_commands(uint8_t command, uint8_t addr, uint8_t data, CanMessage *tx_msg) {
    switch (command) {
        case 0x06: // READ_MEM
            tx_msg->data[0] = memory_space[addr];
            break;
        case 0x07: // WRITE_MEM
            memory_space[addr] = data;
            break;
    }
}

9. Советы по отладки и устранению неполадок

  • Может нюхак: Используйте такие инструменты, как векторное каноэ, PCAN-View или Savvy CAN для мониторинга трафика.
  • Регистрация: Включите серийные операторы печати для каждой обработанной команды.
  • CRC/контрольная сумма: Добавьте CRC на уровне байта для обнаружения коррумпированных сообщений.
  • Сторожевые собаки: Сброс системы, если обработка сообщений висит.
  • Тесты петли: Проверьте, может приемость, эхо отправляя отправленные сообщения.

10. Заключение

Фабрика тестового кода позволяет проверить API драйверов низкого уровня через интерфейс на основе банки. Это особенно полезно в средах HIL, где необходимо повторное автоматизированное тестирование. При надлежащей абстракции такая же настройка FTC может поддерживать различные модули и развивающиеся требования.

Четко структурируя ваши сообщения CAN, создавая обертки API на уровне водителя и поддержав тестовый подход, вы можете ускорить проверку и уменьшить дефекты прошивки.

Пусть эта структура служит отправной точкой для создания более продвинутых тестовых жгутов для встроенного автомобильного программного обеспечения.


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE