Add full automotive RTOS project
Add kernel (Cortex-M0/M3/M4, Tricore, S32K, RISC-V ports), drivers, middleware (CAN stack, diagnostics, safety), applications, board support, build/test tooling, and documentation.
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @file dtc_manager.h
|
||||
* @brief Diagnostic Trouble Code Manager
|
||||
*/
|
||||
|
||||
#ifndef DTC_MANAGER_H
|
||||
#define DTC_MANAGER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "kernel.h"
|
||||
|
||||
/* DTC Configuration */
|
||||
#define DTC_MAX_COUNT 100
|
||||
#define DTC_MAX_SNAPSHOT_RECORDS 5
|
||||
#define DTC_MAX_EXTENDED_DATA 10
|
||||
|
||||
/* DTC Status Bits */
|
||||
typedef struct {
|
||||
uint8_t test_failed : 1;
|
||||
uint8_t test_failed_this_operation_cycle : 1;
|
||||
uint8_t pending_dtc : 1;
|
||||
uint8_t confirmed_dtc : 1;
|
||||
uint8_t test_not_completed_since_last_clear : 1;
|
||||
uint8_t test_failed_since_last_clear : 1;
|
||||
uint8_t test_not_completed_this_operation_cycle : 1;
|
||||
uint8_t warning_indicator_requested : 1;
|
||||
} DtcStatus_t;
|
||||
|
||||
/* DTC Format */
|
||||
typedef struct {
|
||||
uint8_t high_byte;
|
||||
uint8_t middle_byte;
|
||||
uint8_t low_byte;
|
||||
} DtcCode_t;
|
||||
|
||||
/* DTC Snapshot Record */
|
||||
typedef struct {
|
||||
uint16_t record_number;
|
||||
uint8_t* data;
|
||||
uint16_t length;
|
||||
uint32_t timestamp;
|
||||
} DtcSnapshotRecord_t;
|
||||
|
||||
/* DTC Extended Data */
|
||||
typedef struct {
|
||||
uint16_t record_number;
|
||||
uint8_t* data;
|
||||
uint16_t length;
|
||||
} DtcExtendedData_t;
|
||||
|
||||
/* DTC Entry */
|
||||
typedef struct {
|
||||
DtcCode_t code;
|
||||
DtcStatus_t status;
|
||||
uint8_t severity;
|
||||
uint8_t functional_unit;
|
||||
uint32_t occurrence_counter;
|
||||
uint32_t aging_counter;
|
||||
uint32_t first_occurrence_time;
|
||||
uint32_t last_occurrence_time;
|
||||
DtcSnapshotRecord_t snapshots[DTC_MAX_SNAPSHOT_RECORDS];
|
||||
uint8_t snapshot_count;
|
||||
DtcExtendedData_t extended_data[DTC_MAX_EXTENDED_DATA];
|
||||
uint8_t extended_data_count;
|
||||
bool is_active;
|
||||
} DtcEntry_t;
|
||||
|
||||
/* DTC Manager Functions */
|
||||
KernelStatus_t dtc_manager_init(void);
|
||||
KernelStatus_t dtc_manager_deinit(void);
|
||||
KernelStatus_t dtc_manager_add_dtc(const DtcCode_t* code, uint8_t severity);
|
||||
KernelStatus_t dtc_manager_remove_dtc(const DtcCode_t* code);
|
||||
KernelStatus_t dtc_manager_set_status(const DtcCode_t* code, DtcStatus_t status);
|
||||
KernelStatus_t dtc_manager_get_status(const DtcCode_t* code, DtcStatus_t* status);
|
||||
KernelStatus_t dtc_manager_add_snapshot(const DtcCode_t* code,
|
||||
const uint8_t* data, uint16_t length);
|
||||
KernelStatus_t dtc_manager_add_extended_data(const DtcCode_t* code,
|
||||
const uint8_t* data, uint16_t length);
|
||||
KernelStatus_t dtc_manager_clear_all(void);
|
||||
uint16_t dtc_manager_get_count(void);
|
||||
KernelStatus_t dtc_manager_get_dtc(uint16_t index, DtcEntry_t* entry);
|
||||
KernelStatus_t dtc_manager_increment_occurrence(const DtcCode_t* code);
|
||||
void dtc_manager_main_function(void); /* Periodic processing */
|
||||
|
||||
#endif /* DTC_MANAGER_H */
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @file obd_ii.h
|
||||
* @brief OBD-II (On-Board Diagnostics) implementation
|
||||
*/
|
||||
|
||||
#ifndef OBD_II_H
|
||||
#define OBD_II_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "kernel.h"
|
||||
#include "can_driver.h"
|
||||
|
||||
/* OBD-II Configuration */
|
||||
#define OBD_II_MAX_PIDS 0xFF
|
||||
#define OBD_II_CAN_ID_REQUEST 0x7DF
|
||||
#define OBD_II_CAN_ID_RESPONSE 0x7E8
|
||||
#define OBD_II_CAN_ID_RESPONSE_2 0x7E9
|
||||
|
||||
/* OBD-II Service Modes */
|
||||
typedef enum {
|
||||
OBD_II_SERVICE_SHOW_CURRENT_DATA = 0x01,
|
||||
OBD_II_SERVICE_SHOW_FREEZE_FRAME = 0x02,
|
||||
OBD_II_SERVICE_SHOW_STORED_DTCS = 0x03,
|
||||
OBD_II_SERVICE_CLEAR_DTCS = 0x04,
|
||||
OBD_II_SERVICE_TEST_RESULTS_OXYGEN = 0x05,
|
||||
OBD_II_SERVICE_TEST_RESULTS_NON_CONTINUOUS = 0x06,
|
||||
OBD_II_SERVICE_SHOW_PENDING_DTCS = 0x07,
|
||||
OBD_II_SERVICE_CONTROL_ONBOARD_SYSTEM = 0x08,
|
||||
OBD_II_SERVICE_REQUEST_VEHICLE_INFO = 0x09,
|
||||
OBD_II_SERVICE_PERMANENT_DTCS = 0x0A
|
||||
} ObdIIServiceMode_t;
|
||||
|
||||
/* OBD-II PID Definitions */
|
||||
typedef enum {
|
||||
OBD_II_PID_SUPPORTED_00_20 = 0x00,
|
||||
OBD_II_PID_MONITOR_STATUS = 0x01,
|
||||
OBD_II_PID_FREEZE_DTC = 0x02,
|
||||
OBD_II_PID_FUEL_SYSTEM_STATUS = 0x03,
|
||||
OBD_II_PID_CALCULATED_ENGINE_LOAD = 0x04,
|
||||
OBD_II_PID_ENGINE_COOLANT_TEMP = 0x05,
|
||||
OBD_II_PID_SHORT_TERM_FUEL_TRIM_BANK1 = 0x06,
|
||||
OBD_II_PID_LONG_TERM_FUEL_TRIM_BANK1 = 0x07,
|
||||
OBD_II_PID_INTAKE_MANIFOLD_PRESSURE = 0x0B,
|
||||
OBD_II_PID_ENGINE_RPM = 0x0C,
|
||||
OBD_II_PID_VEHICLE_SPEED = 0x0D,
|
||||
OBD_II_PID_TIMING_ADVANCE = 0x0E,
|
||||
OBD_II_PID_INTAKE_AIR_TEMP = 0x0F,
|
||||
OBD_II_PID_MAF_AIR_FLOW_RATE = 0x10,
|
||||
OBD_II_PID_THROTTLE_POSITION = 0x11,
|
||||
OBD_II_PID_OXYGEN_SENSOR_PRESENT = 0x13,
|
||||
OBD_II_PID_OXYGEN_SENSOR_1 = 0x14,
|
||||
OBD_II_PID_OXYGEN_SENSOR_2 = 0x15,
|
||||
OBD_II_PID_RUN_TIME_SINCE_START = 0x1F,
|
||||
OBD_II_PID_SUPPORTED_21_40 = 0x20,
|
||||
OBD_II_PID_DISTANCE_WITH_MIL = 0x21,
|
||||
OBD_II_PID_FUEL_RAIL_PRESSURE = 0x22,
|
||||
OBD_II_PID_FUEL_RAIL_GAUGE_PRESSURE = 0x23,
|
||||
OBD_II_PID_OXYGEN_SENSOR_3 = 0x24,
|
||||
OBD_II_PID_OXYGEN_SENSOR_4 = 0x25,
|
||||
OBD_II_PID_SUPPORTED_41_60 = 0x40,
|
||||
OBD_II_PID_CONTROL_MODULE_VOLTAGE = 0x42,
|
||||
OBD_II_PID_ABSOLUTE_LOAD_VALUE = 0x43,
|
||||
OBD_II_PID_AMBIENT_AIR_TEMP = 0x46,
|
||||
OBD_II_PID_THROTTLE_POSITION_B = 0x47,
|
||||
OBD_II_PID_ACCELERATOR_PEDAL_POSITION_D = 0x49,
|
||||
OBD_II_PID_ACCELERATOR_PEDAL_POSITION_E = 0x4A
|
||||
} ObdIIPid_t;
|
||||
|
||||
/* OBD-II PID Value */
|
||||
typedef struct {
|
||||
ObdIIPid_t pid;
|
||||
uint8_t data[4];
|
||||
uint8_t length;
|
||||
bool is_supported;
|
||||
} ObdIIPidValue_t;
|
||||
|
||||
/* OBD-II Callbacks */
|
||||
typedef bool (*ObdIIPidRequestCallback_t)(ObdIIPid_t pid, uint8_t* data,
|
||||
uint8_t* length);
|
||||
typedef void (*ObdIIDtcRequestCallback_t)(uint8_t* dtc_data, uint16_t* length);
|
||||
|
||||
/* OBD-II Functions */
|
||||
KernelStatus_t obd_ii_init(void);
|
||||
KernelStatus_t obd_ii_deinit(void);
|
||||
KernelStatus_t obd_ii_register_pid_callback(ObdIIPidRequestCallback_t callback);
|
||||
KernelStatus_t obd_ii_register_dtc_callback(ObdIIDtcRequestCallback_t callback);
|
||||
void obd_ii_process_request(const CanMessage_t* message);
|
||||
void obd_ii_main_function(void);
|
||||
|
||||
#endif /* OBD_II_H */
|
||||
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* @file dtc_manager.c
|
||||
* @brief DTC Manager implementation
|
||||
*/
|
||||
|
||||
#include "dtc_manager.h"
|
||||
#include <string.h>
|
||||
|
||||
/* DTC Manager State */
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
DtcEntry_t dtc_entries[DTC_MAX_COUNT];
|
||||
uint16_t dtc_count;
|
||||
Mutex_t mutex;
|
||||
} DtcManagerState_t;
|
||||
|
||||
static DtcManagerState_t dtc_manager;
|
||||
|
||||
/* Initialize DTC Manager */
|
||||
KernelStatus_t dtc_manager_init(void) {
|
||||
if (dtc_manager.initialized) {
|
||||
return KERNEL_ERROR;
|
||||
}
|
||||
|
||||
memset(&dtc_manager, 0, sizeof(DtcManagerState_t));
|
||||
mutex_create(&dtc_manager.mutex, false);
|
||||
|
||||
dtc_manager.initialized = true;
|
||||
return KERNEL_OK;
|
||||
}
|
||||
|
||||
/* Add DTC */
|
||||
KernelStatus_t dtc_manager_add_dtc(const DtcCode_t* code, uint8_t severity) {
|
||||
if (!dtc_manager.initialized || code == NULL) {
|
||||
return KERNEL_ERROR;
|
||||
}
|
||||
|
||||
mutex_lock(&dtc_manager.mutex, 100);
|
||||
|
||||
/* Check if DTC already exists */
|
||||
for (uint16_t i = 0; i < dtc_manager.dtc_count; i++) {
|
||||
if (dtc_manager.dtc_entries[i].code.high_byte == code->high_byte &&
|
||||
dtc_manager.dtc_entries[i].code.middle_byte == code->middle_byte &&
|
||||
dtc_manager.dtc_entries[i].code.low_byte == code->low_byte) {
|
||||
mutex_unlock(&dtc_manager.mutex);
|
||||
return KERNEL_OK; /* DTC already exists */
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if maximum DTCs reached */
|
||||
if (dtc_manager.dtc_count >= DTC_MAX_COUNT) {
|
||||
mutex_unlock(&dtc_manager.mutex);
|
||||
return KERNEL_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Add new DTC */
|
||||
DtcEntry_t* entry = &dtc_manager.dtc_entries[dtc_manager.dtc_count];
|
||||
entry->code = *code;
|
||||
entry->status.test_failed = 1;
|
||||
entry->status.test_failed_this_operation_cycle = 1;
|
||||
entry->severity = severity;
|
||||
entry->occurrence_counter = 1;
|
||||
entry->first_occurrence_time = kernel_get_tick_count();
|
||||
entry->last_occurrence_time = entry->first_occurrence_time;
|
||||
entry->is_active = true;
|
||||
|
||||
dtc_manager.dtc_count++;
|
||||
|
||||
mutex_unlock(&dtc_manager.mutex);
|
||||
|
||||
return KERNEL_OK;
|
||||
}
|
||||
|
||||
/* Remove DTC */
|
||||
KernelStatus_t dtc_manager_remove_dtc(const DtcCode_t* code) {
|
||||
if (!dtc_manager.initialized || code == NULL) {
|
||||
return KERNEL_ERROR;
|
||||
}
|
||||
|
||||
mutex_lock(&dtc_manager.mutex, 100);
|
||||
|
||||
for (uint16_t i = 0; i < dtc_manager.dtc_count; i++) {
|
||||
if (dtc_manager.dtc_entries[i].code.high_byte == code->high_byte &&
|
||||
dtc_manager.dtc_entries[i].code.middle_byte == code->middle_byte &&
|
||||
dtc_manager.dtc_entries[i].code.low_byte == code->low_byte) {
|
||||
/* Remove DTC */
|
||||
for (uint16_t j = i; j < dtc_manager.dtc_count - 1; j++) {
|
||||
dtc_manager.dtc_entries[j] = dtc_manager.dtc_entries[j + 1];
|
||||
}
|
||||
dtc_manager.dtc_count--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&dtc_manager.mutex);
|
||||
|
||||
return KERNEL_OK;
|
||||
}
|
||||
|
||||
/* Set DTC Status */
|
||||
KernelStatus_t dtc_manager_set_status(const DtcCode_t* code, DtcStatus_t status) {
|
||||
if (!dtc_manager.initialized || code == NULL) {
|
||||
return KERNEL_ERROR;
|
||||
}
|
||||
|
||||
mutex_lock(&dtc_manager.mutex, 100);
|
||||
|
||||
for (uint16_t i = 0; i < dtc_manager.dtc_count; i++) {
|
||||
if (dtc_manager.dtc_entries[i].code.high_byte == code->high_byte &&
|
||||
dtc_manager.dtc_entries[i].code.middle_byte == code->middle_byte &&
|
||||
dtc_manager.dtc_entries[i].code.low_byte == code->low_byte) {
|
||||
dtc_manager.dtc_entries[i].status = status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&dtc_manager.mutex);
|
||||
|
||||
return KERNEL_OK;
|
||||
}
|
||||
|
||||
/* Add Snapshot */
|
||||
KernelStatus_t dtc_manager_add_snapshot(const DtcCode_t* code,
|
||||
const uint8_t* data, uint16_t length) {
|
||||
if (!dtc_manager.initialized || code == NULL || data == NULL) {
|
||||
return KERNEL_ERROR;
|
||||
}
|
||||
|
||||
mutex_lock(&dtc_manager.mutex, 100);
|
||||
|
||||
for (uint16_t i = 0; i < dtc_manager.dtc_count; i++) {
|
||||
if (dtc_manager.dtc_entries[i].code.high_byte == code->high_byte &&
|
||||
dtc_manager.dtc_entries[i].code.middle_byte == code->middle_byte &&
|
||||
dtc_manager.dtc_entries[i].code.low_byte == code->low_byte) {
|
||||
|
||||
DtcEntry_t* entry = &dtc_manager.dtc_entries[i];
|
||||
|
||||
if (entry->snapshot_count < DTC_MAX_SNAPSHOT_RECORDS) {
|
||||
DtcSnapshotRecord_t* snapshot =
|
||||
&entry->snapshots[entry->snapshot_count];
|
||||
|
||||
snapshot->record_number = entry->snapshot_count + 1;
|
||||
snapshot->data = (uint8_t*)malloc(length);
|
||||
memcpy(snapshot->data, data, length);
|
||||
snapshot->length = length;
|
||||
snapshot->timestamp = kernel_get_tick_count();
|
||||
|
||||
entry->snapshot_count++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&dtc_manager.mutex);
|
||||
|
||||
return KERNEL_OK;
|
||||
}
|
||||
|
||||
/* Clear All DTCs */
|
||||
KernelStatus_t dtc_manager_clear_all(void) {
|
||||
if (!dtc_manager.initialized) {
|
||||
return KERNEL_ERROR;
|
||||
}
|
||||
|
||||
mutex_lock(&dtc_manager.mutex, 100);
|
||||
|
||||
/* Free snapshot data */
|
||||
for (uint16_t i = 0; i < dtc_manager.dtc_count; i++) {
|
||||
DtcEntry_t* entry = &dtc_manager.dtc_entries[i];
|
||||
|
||||
for (uint8_t j = 0; j < entry->snapshot_count; j++) {
|
||||
if (entry->snapshots[j].data != NULL) {
|
||||
free(entry->snapshots[j].data);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t j = 0; j < entry->extended_data_count; j++) {
|
||||
if (entry->extended_data[j].data != NULL) {
|
||||
free(entry->extended_data[j].data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all DTCs */
|
||||
dtc_manager.dtc_count = 0;
|
||||
|
||||
mutex_unlock(&dtc_manager.mutex);
|
||||
|
||||
return KERNEL_OK;
|
||||
}
|
||||
|
||||
/* Get DTC Count */
|
||||
uint16_t dtc_manager_get_count(void) {
|
||||
return dtc_manager.dtc_count;
|
||||
}
|
||||
|
||||
/* Increment Occurrence Counter */
|
||||
KernelStatus_t dtc_manager_increment_occurrence(const DtcCode_t* code) {
|
||||
if (!dtc_manager.initialized || code == NULL) {
|
||||
return KERNEL_ERROR;
|
||||
}
|
||||
|
||||
mutex_lock(&dtc_manager.mutex, 100);
|
||||
|
||||
for (uint16_t i = 0; i < dtc_manager.dtc_count; i++) {
|
||||
if (dtc_manager.dtc_entries[i].code.high_byte == code->high_byte &&
|
||||
dtc_manager.dtc_entries[i].code.middle_byte == code->middle_byte &&
|
||||
dtc_manager.dtc_entries[i].code.low_byte == code->low_byte) {
|
||||
|
||||
dtc_manager.dtc_entries[i].occurrence_counter++;
|
||||
dtc_manager.dtc_entries[i].last_occurrence_time = kernel_get_tick_count();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&dtc_manager.mutex);
|
||||
|
||||
return KERNEL_OK;
|
||||
}
|
||||
|
||||
/* DTC Manager Main Function */
|
||||
void dtc_manager_main_function(void) {
|
||||
if (!dtc_manager.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&dtc_manager.mutex, 100);
|
||||
|
||||
/* Update DTC aging */
|
||||
for (uint16_t i = 0; i < dtc_manager.dtc_count; i++) {
|
||||
DtcEntry_t* entry = &dtc_manager.dtc_entries[i];
|
||||
|
||||
/* Update aging counter */
|
||||
if (entry->status.test_failed) {
|
||||
entry->aging_counter++;
|
||||
} else {
|
||||
entry->aging_counter = 0;
|
||||
}
|
||||
|
||||
/* Update status based on aging */
|
||||
if (entry->aging_counter > 40) {
|
||||
entry->status.confirmed_dtc = 1;
|
||||
entry->status.pending_dtc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&dtc_manager.mutex);
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* @file obd_ii.c
|
||||
* @brief OBD-II implementation
|
||||
*/
|
||||
|
||||
#include "obd_ii.h"
|
||||
#include "dtc_manager.h"
|
||||
#include <string.h>
|
||||
|
||||
/* OBD-II State */
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
ObdIIPidRequestCallback_t pid_callback;
|
||||
ObdIIDtcRequestCallback_t dtc_callback;
|
||||
Mutex_t mutex;
|
||||
} ObdIIState_t;
|
||||
|
||||
static ObdIIState_t obd_ii_state;
|
||||
|
||||
/* Initialize OBD-II */
|
||||
KernelStatus_t obd_ii_init(void) {
|
||||
if (obd_ii_state.initialized) {
|
||||
return KERNEL_ERROR;
|
||||
}
|
||||
|
||||
memset(&obd_ii_state, 0, sizeof(ObdIIState_t));
|
||||
mutex_create(&obd_ii_state.mutex, false);
|
||||
|
||||
obd_ii_state.initialized = true;
|
||||
return KERNEL_OK;
|
||||
}
|
||||
|
||||
/* Register PID Callback */
|
||||
KernelStatus_t obd_ii_register_pid_callback(ObdIIPidRequestCallback_t callback) {
|
||||
if (!obd_ii_state.initialized || callback == NULL) {
|
||||
return KERNEL_ERROR;
|
||||
}
|
||||
|
||||
obd_ii_state.pid_callback = callback;
|
||||
return KERNEL_OK;
|
||||
}
|
||||
|
||||
/* Register DTC Callback */
|
||||
KernelStatus_t obd_ii_register_dtc_callback(ObdIIDtcRequestCallback_t callback) {
|
||||
if (!obd_ii_state.initialized || callback == NULL) {
|
||||
return KERNEL_ERROR;
|
||||
}
|
||||
|
||||
obd_ii_state.dtc_callback = callback;
|
||||
return KERNEL_OK;
|
||||
}
|
||||
|
||||
/* Process OBD-II Request */
|
||||
void obd_ii_process_request(const CanMessage_t* message) {
|
||||
if (!obd_ii_state.initialized || message == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if OBD-II request */
|
||||
if (message->id.id != OBD_II_CAN_ID_REQUEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&obd_ii_state.mutex, 100);
|
||||
|
||||
/* Parse request */
|
||||
uint8_t mode = message->data[1];
|
||||
uint8_t pid = message->data[2];
|
||||
|
||||
CanMessage_t response;
|
||||
response.id.id = OBD_II_CAN_ID_RESPONSE;
|
||||
response.id.is_extended = false;
|
||||
|
||||
switch (mode) {
|
||||
case OBD_II_SERVICE_SHOW_CURRENT_DATA:
|
||||
/* Handle PID request */
|
||||
if (obd_ii_state.pid_callback != NULL) {
|
||||
uint8_t data[4];
|
||||
uint8_t length = 0;
|
||||
|
||||
if (obd_ii_state.pid_callback((ObdIIPid_t)pid, data, &length)) {
|
||||
response.length = 5 + length;
|
||||
response.data[0] = 0x04; /* Number of additional bytes */
|
||||
response.data[1] = 0x41; /* Mode 1 response */
|
||||
response.data[2] = pid;
|
||||
memcpy(&response.data[3], data, length);
|
||||
} else {
|
||||
/* PID not supported */
|
||||
response.length = 3;
|
||||
response.data[0] = 0x02;
|
||||
response.data[1] = 0x7F;
|
||||
response.data[2] = 0x11; /* Service not supported */
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OBD_II_SERVICE_SHOW_STORED_DTCS:
|
||||
/* Handle DTC request */
|
||||
if (obd_ii_state.dtc_callback != NULL) {
|
||||
uint8_t dtc_data[100];
|
||||
uint16_t dtc_length = 0;
|
||||
|
||||
obd_ii_state.dtc_callback(dtc_data, &dtc_length);
|
||||
|
||||
response.length = dtc_length + 3;
|
||||
response.data[0] = dtc_length + 2;
|
||||
response.data[1] = 0x43; /* Mode 3 response */
|
||||
memcpy(&response.data[2], dtc_data, dtc_length);
|
||||
}
|
||||
break;
|
||||
|
||||
case OBD_II_SERVICE_CLEAR_DTCS:
|
||||
/* Clear DTCs */
|
||||
dtc_manager_clear_all();
|
||||
|
||||
response.length = 2;
|
||||
response.data[0] = 0x01;
|
||||
response.data[1] = 0x44; /* Mode 4 response */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Service not supported */
|
||||
response.length = 3;
|
||||
response.data[0] = 0x02;
|
||||
response.data[1] = 0x7F;
|
||||
response.data[2] = 0x11;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Send response */
|
||||
can_send_message(&response, 100);
|
||||
|
||||
mutex_unlock(&obd_ii_state.mutex);
|
||||
}
|
||||
Reference in New Issue
Block a user