Expose the existing registers through Modbus and service CAN using one GAS provider only in M95M02 builds. Include the EEPROM layout/driver, LOAD protection and calibration, firmware identity and shared CCS build workflow. Add transport/profile and SCI8 validation tests, documentation and the checked M95M02 firmware image.
64 lines
2.2 KiB
C
64 lines
2.2 KiB
C
#include "gas167.h"
|
|
#if EEPROM_M95M02
|
|
#include "package.h"
|
|
|
|
extern int modbus[];
|
|
extern int Desk;
|
|
extern void ump_log_rs(void);
|
|
|
|
static const uint16_t gas167_info[GAS167_INFO_WORDS] = {
|
|
0x4741U, 0x5331U, GAS167_PROFILE_VERSION, 167U,
|
|
GAS167_REG_BASE, GAS167_REG_COUNT, GAS167_CAPABILITIES, 1U
|
|
};
|
|
|
|
int gas167_contains(uint16_t address)
|
|
{
|
|
return (uint16_t)(address - GAS167_REG_BASE) < GAS167_REG_COUNT ||
|
|
(uint16_t)(address - GAS167_INFO_BASE) < GAS167_INFO_WORDS;
|
|
}
|
|
|
|
static unsigned gas167_write(uint16_t offset, uint16_t value)
|
|
{
|
|
/* Match the existing native Modbus write policy. These status words
|
|
* cannot be overwritten and an invalid timeout cannot bypass protection. */
|
|
if (Desk == dsk_LOAD && (offset == 0x7CU || offset == 0x7DU)) return 2;
|
|
if (Desk == dsk_LOAD && offset == 0x52U &&
|
|
(value == 0U || value > 60000U)) return 3;
|
|
/* C28x int is one register word; reads always expose the raw uint16_t. */
|
|
modbus[offset] = (int)value;
|
|
if (offset == 127U) ump_log_rs();
|
|
return 0;
|
|
}
|
|
|
|
unsigned gas167_prepare(unsigned function, uint16_t address, uint16_t value,
|
|
int can, uint16_t *reply, unsigned *error)
|
|
{
|
|
uint16_t offset;
|
|
unsigned i, available;
|
|
int info;
|
|
if (!reply || !error) return 0;
|
|
*error = 0;
|
|
info = (uint16_t)(address - GAS167_INFO_BASE) < GAS167_INFO_WORDS;
|
|
offset = (uint16_t)(address - (info ? GAS167_INFO_BASE : GAS167_REG_BASE));
|
|
available = info ? GAS167_INFO_WORDS : GAS167_REG_COUNT;
|
|
if (function != 3U && function != 6U) *error = 1;
|
|
else if (offset >= available) *error = 2;
|
|
else if (function == 6U) {
|
|
*error = info ? 2U : gas167_write(offset, value);
|
|
} else if (!value || value > GAS167_MAX_WORDS || (can && (value & 1U))) {
|
|
*error = 3;
|
|
} else if (value > available - offset) {
|
|
*error = 2;
|
|
} else {
|
|
/* Validate the entire block before reading. A block cannot cross a
|
|
* region boundary, wrap at 0xFFFF, or leak the hidden parameter word. */
|
|
for (i = 0; i < value; ++i)
|
|
reply[i] = info ? gas167_info[offset+i] : (uint16_t)modbus[offset+i];
|
|
return value;
|
|
}
|
|
reply[0] = address;
|
|
reply[1] = value;
|
|
return 2;
|
|
}
|
|
#endif
|