GDI4: support multiple PT2001 chips

PB3 is used as CS for second chip.
BP4, PB5 control DRVEN and RESETB of both chips.
This commit is contained in:
Andrey Gusakov 2025-01-29 14:12:55 +03:00 committed by rusefillc
parent be3ae6033d
commit f9e7c587ea
7 changed files with 169 additions and 92 deletions

View File

@ -1,6 +1,8 @@
#include "can.h"
#include "hal.h"
#include "efifeatures.h"
#include <cstdint>
#include <cstring>
#include "sent_canbus_protocol.h"
@ -21,7 +23,7 @@
static char VERSION[] = {compilationYear() / 100, compilationYear() % 100, compilationMonth(), compilationDay()};
extern GDIConfiguration configuration;
extern Pt2001 chip;
extern Pt2001 chips[EFI_PT2001_CHIPS];
extern bool isOverallHappyStatus;
static const CANConfig canConfig500 =
@ -44,17 +46,17 @@ static void countTxResult(msg_t msg) {
}
}
int canGetOutputCanIdBase(void)
int canGetOutputCanIdBase(size_t chip)
{
return (configuration.outputCanID + boardGetId() * GDI4_BASE_ADDRESS_OFFSET);
return (configuration.outputCanID + (boardGetId() + chip) * GDI4_BASE_ADDRESS_OFFSET);
}
int canGetInputCanIdBase()
int canGetInputCanIdBase(size_t chip)
{
return (configuration.inputCanID + boardGetId() * GDI4_BASE_ADDRESS_OFFSET);
return (configuration.inputCanID + (boardGetId() + chip) * GDI4_BASE_ADDRESS_OFFSET);
}
void SendSomething(int baseID) {
void SendSomething(size_t chip, int baseID) {
CANTxFrame m_frame;
m_frame.IDE = CAN_IDE_EXT;
@ -67,7 +69,7 @@ void SendSomething(int baseID) {
m_frame.data8[0] = configuration.inputCanID;
m_frame.data8[1] = configuration.updateCounter;
m_frame.data8[2] = isOverallHappyStatus;
m_frame.data8[6] = (int)chip.fault;
m_frame.data8[6] = (int)chips[chip].fault;
m_frame.data8[7] = GDI4_MAGIC;
msg_t msg = canTransmitTimeout(&CAND1, CAN_ANY_MAILBOX, &m_frame, CAN_TX_TIMEOUT_100_MS);
@ -163,6 +165,8 @@ static int intTxCounter = 0;
static THD_WORKING_AREA(waCanTxThread, 256);
void CanTxThread(void*)
{
chRegSetThreadName("CAN TX");
while (1) {
intTxCounter++;
chThdSleepMilliseconds(1000 / CAN_TX_PERIOD_MS);
@ -171,19 +175,23 @@ void CanTxThread(void*)
continue; // we were told to be silent
}
// keep constant while sending whole banch of messages
int outID = canGetOutputCanIdBase();
for (size_t i = 0; i < EFI_PT2001_CHIPS; i++) {
// keep constant while sending whole banch of messages
int outID = canGetOutputCanIdBase(i);
if (intTxCounter % (1000 / CAN_TX_PERIOD_MS) == 0) {
sendOutConfiguration(outID);
if (intTxCounter % (1000 / CAN_TX_PERIOD_MS) == 0) {
sendOutConfiguration(outID);
}
if (intTxCounter % (1000 / CAN_TX_PERIOD_MS) == 0) {
sendOutVersion(outID);
}
SendSomething(i, outID);
if (i == 0) {
sendOutSentData(outID);
}
}
if (intTxCounter % (1000 / CAN_TX_PERIOD_MS) == 0) {
sendOutVersion(outID);
}
SendSomething(outID);
sendOutSentData(outID);
}
}
@ -205,6 +213,8 @@ static float getFloat(CANRxFrame *frame, int offset) {
static THD_WORKING_AREA(waCanRxThread, 256);
void CanRxThread(void*)
{
chRegSetThreadName("CAN RX");
while (1) {
CANRxFrame frame;
msg_t msg = canReceiveTimeout(&CAND1, CAN_ANY_MAILBOX, &frame, TIME_INFINITE);
@ -213,13 +223,6 @@ void CanRxThread(void*)
if (msg != MSG_OK) {
continue;
}
size_t writeCount = 0;
// writeCount = chsnprintf(printBuffer, sizeof(printBuffer), "eid=%d data[0]=%d dlc=%d\n\n\n\n\n\n\n",
// frame.EID,
// frame.data8[0],
// frame.DLC);
// Ignore std frames, only listen to ext
if (frame.IDE != CAN_IDE_EXT) {
@ -231,35 +234,44 @@ void CanRxThread(void*)
continue;
}
bool withNewValue = false;
int inputID = canGetInputCanIdBase();
// TODO: valudate DLC and IDE
if (frame.EID == inputID) {
ASSIGN_IF_CHANGED(configuration.BoostVoltage, getInt(&frame, 1));
ASSIGN_IF_CHANGED(configuration.BoostCurrent, getFloat(&frame, 3));
ASSIGN_IF_CHANGED(configuration.TBoostMin, getInt(&frame, 5));
} else if (frame.EID == inputID + 1) {
ASSIGN_IF_CHANGED(configuration.TBoostMax, getInt(&frame, 1));
ASSIGN_IF_CHANGED(configuration.PeakCurrent, getFloat(&frame, 3));
ASSIGN_IF_CHANGED(configuration.TpeakDuration, getInt(&frame, 5));
} else if (frame.EID == inputID + 2) {
ASSIGN_IF_CHANGED(configuration.TpeakOff, getInt(&frame, 1));
ASSIGN_IF_CHANGED(configuration.Tbypass, getInt(&frame, 3));
ASSIGN_IF_CHANGED(configuration.HoldCurrent, getFloat(&frame, 5));
} else if (frame.EID == inputID + 3) {
ASSIGN_IF_CHANGED(configuration.TholdOff, getInt(&frame, 1));
ASSIGN_IF_CHANGED(configuration.THoldDuration, getInt(&frame, 3));
ASSIGN_IF_CHANGED(configuration.PumpPeakCurrent, getFloat(&frame, 5));
} else if (frame.EID == inputID + 4) {
ASSIGN_IF_CHANGED(configuration.PumpHoldCurrent, getFloat(&frame, 1));
ASSIGN_IF_CHANGED(configuration.outputCanID, getInt(&frame, 3));
for (size_t i = 0; i < EFI_PT2001_CHIPS; i++) {
// size_t writeCount = 0;
// writeCount = chsnprintf(printBuffer, sizeof(printBuffer), "eid=%d data[0]=%d dlc=%d\n\n\n\n\n\n\n",
// frame.EID,
// frame.data8[0],
// frame.DLC);
bool withNewValue = false;
int inputID = canGetInputCanIdBase(i);
// TODO: valudate DLC and IDE
if (frame.EID == inputID) {
ASSIGN_IF_CHANGED(configuration.BoostVoltage, getInt(&frame, 1));
ASSIGN_IF_CHANGED(configuration.BoostCurrent, getFloat(&frame, 3));
ASSIGN_IF_CHANGED(configuration.TBoostMin, getInt(&frame, 5));
} else if (frame.EID == inputID + 1) {
ASSIGN_IF_CHANGED(configuration.TBoostMax, getInt(&frame, 1));
ASSIGN_IF_CHANGED(configuration.PeakCurrent, getFloat(&frame, 3));
ASSIGN_IF_CHANGED(configuration.TpeakDuration, getInt(&frame, 5));
} else if (frame.EID == inputID + 2) {
ASSIGN_IF_CHANGED(configuration.TpeakOff, getInt(&frame, 1));
ASSIGN_IF_CHANGED(configuration.Tbypass, getInt(&frame, 3));
ASSIGN_IF_CHANGED(configuration.HoldCurrent, getFloat(&frame, 5));
} else if (frame.EID == inputID + 3) {
ASSIGN_IF_CHANGED(configuration.TholdOff, getInt(&frame, 1));
ASSIGN_IF_CHANGED(configuration.THoldDuration, getInt(&frame, 3));
ASSIGN_IF_CHANGED(configuration.PumpPeakCurrent, getFloat(&frame, 5));
} else if (frame.EID == inputID + 4) {
ASSIGN_IF_CHANGED(configuration.PumpHoldCurrent, getFloat(&frame, 1));
ASSIGN_IF_CHANGED(configuration.outputCanID, getInt(&frame, 3));
}
if (withNewValue) {
saveConfiguration();
chips[i].restart();
}
// if (writeCount > 0)
// uartStartSend(&UARTD1, writeCount, printBuffer);
}
if (withNewValue) {
saveConfiguration();
chip.restart();
}
// if (writeCount > 0)
// uartStartSend(&UARTD1, writeCount, printBuffer);
chThdSleepMilliseconds(100);
}

View File

@ -1,5 +1,9 @@
#pragma once
#include <cstdint>
#include <cstddef>
int canGetOutputCanIdBase(size_t chip);
int canGetInputCanIdBase(size_t chip);
void InitCan();

View File

@ -0,0 +1,11 @@
/**
* @file efifeatures.h
*
* @brief In this header we can configure which firmware modules are used.
*/
#pragma once
#ifndef EFI_PT2001_CHIPS
#define EFI_PT2001_CHIPS 1
#endif

View File

@ -1,3 +1,5 @@
#include "efifeatures.h"
#include "pt2001impl.h"
#include "can.h"
@ -24,16 +26,31 @@ static void InitPins() {
bool isOverallHappyStatus = false;
static const SPIConfig spiCfg = {
.circular = false,
.end_cb = nullptr,
.ssport = GPIOB,
.sspad = 2,
.cr1 =
SPI_CR1_DFF |
SPI_CR1_MSTR |
SPI_CR1_CPHA | SPI_CR1_BR_1 | SPI_CR1_SPE,
static const SPIConfig spiCfg[EFI_PT2001_CHIPS] = {
{
.circular = false,
.end_cb = nullptr,
.ssport = GPIOB,
.sspad = 2,
.cr1 =
SPI_CR1_DFF |
SPI_CR1_MSTR |
SPI_CR1_CPHA | SPI_CR1_BR_1 | SPI_CR1_SPE,
.cr2 = SPI_CR2_SSOE
},
#if (EFI_PT2001_CHIPS > 1)
{
.circular = false,
.end_cb = nullptr,
.ssport = GPIOB,
.sspad = 3,
.cr1 =
SPI_CR1_DFF |
SPI_CR1_MSTR |
SPI_CR1_CPHA | SPI_CR1_BR_1 | SPI_CR1_SPE,
.cr2 = SPI_CR2_SSOE
},
#endif
};
void GDIConfiguration::resetToDefaults() {
@ -68,8 +85,7 @@ GDIConfiguration *getConfiguration() {
return &configuration;
}
bool Pt2001::init() {
void initPt2001Interface() {
palSetPadMode(GPIOA, 5, PAL_MODE_STM32_ALTERNATE_PUSHPULL); // sck
palSetPadMode(GPIOA, 6, PAL_MODE_INPUT); // miso
palSetPadMode(GPIOA, 7, PAL_MODE_STM32_ALTERNATE_PUSHPULL); // mosi
@ -79,6 +95,11 @@ bool Pt2001::init() {
palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL); // chip select
palSetPad(GPIOB, 2);
#if (EFI_PT2001_CHIPS > 1)
palSetPadMode(GPIOB, 3, PAL_MODE_OUTPUT_PUSHPULL); // chip select for second chip
palSetPad(GPIOB, 3);
#endif
// Set debug pins remap mode to use PB4 as normal pin
AFIO->MAPR = AFIO_MAPR_SWJ_CFG_JTAGDISABLE;
palSetPadMode(GPIOB, 4, PAL_MODE_OUTPUT_PUSHPULL); // DRVEN
@ -88,18 +109,19 @@ bool Pt2001::init() {
palClearPad(GPIOB, 5);
palSetPadMode(GPIOB, 7, PAL_MODE_INPUT_PULLDOWN); // flag0
}
driver = &SPID1;
spiStart(driver, &spiCfg);
bool Pt2001::init(SPIDriver *spi, const SPIConfig *cfg) {
driver = spi;
spiCfg = cfg;
spiStart(driver, spiCfg);
spiUnselect(driver);
// Wait 1/2 second for things to wake up
chThdSleepMilliseconds(500);
return restart();
}
Pt2001 chip;
Pt2001 chips[EFI_PT2001_CHIPS];
mfs_error_t flashState;
@ -127,10 +149,15 @@ int main() {
palSetPadMode(LED_GREEN_PORT, LED_GREEN_PIN, PAL_MODE_OUTPUT_PUSHPULL);
palClearPad(LED_GREEN_PORT, LED_GREEN_PIN);
bool isOverallHappyStatus = false;
bool isOverallHappyStatus = true;
initPt2001Interface();
// Wait 1/2 second for things to wake up
chThdSleepMilliseconds(500);
// reminder that +12v is required for PT2001 to start
isOverallHappyStatus = chip.init();
for (size_t i = 0; i < EFI_PT2001_CHIPS; i++) {
isOverallHappyStatus &= chips[i].init(&SPID1, &spiCfg[i]);
}
while (true) {
if (isOverallHappyStatus) {

View File

@ -10,6 +10,7 @@ class Pt2001 : public Pt2001Base {
public:
// returns true if init successful
bool init();
bool init(SPIDriver *spi, const SPIConfig *cfg);
protected:
void acquireBus() override {
@ -19,14 +20,23 @@ protected:
}
void select() override {
/* Acquire ownership of the bus. */
spiAcquireBus(driver);
/* Setup transfer parameters. */
spiStart(driver, spiCfg);
/* Slave Select assertion. */
spiSelect(driver);
}
void deselect() override {
/* Slave Select de-assertion. */
spiUnselect(driver);
/* Ownership release. */
spiReleaseBus(driver);
}
bool errorOnUnexpectedFlag() override {
return false;
}
uint16_t sendRecv(uint16_t tx) override {
@ -141,4 +151,5 @@ protected:
private:
SPIDriver* driver;
const SPIConfig* spiCfg;
};

View File

@ -205,7 +205,7 @@ void sent_channel::Info() {
chprintf(chp, "Interval errors %lu short, %lu long\r\n", statistic.ShortIntervalErr, statistic.LongIntervalErr);
chprintf(chp, "Total frames %lu with CRC error %lu (%d%%)\r\n", statistic.FrameCnt, statistic.CrcErrCnt, 100 * statistic.CrcErrCnt / statistic.FrameCnt);
chprintf(chp, "Total slow channel messages %lu + %lu with crc6 errors %lu (%d%%)\r\n", statistic.sc12, statistic.sc16, statistic.scCrcErr, 100 * statistic.scCrcErr / (statistic.sc12 + statistic.sc16));
chprintf(chp, "Sync errors %lu alive=%d\n", statistic.SyncErr, aliveCounter++);
chprintf(chp, "Sync errors %lu alive=%d\r\n", statistic.SyncErr, aliveCounter++);
#endif
GmPressureDebug();
}
@ -249,6 +249,8 @@ void SENT_ISR_Handler(uint8_t channel, uint16_t clocks, uint8_t flags) {
/* Decoder thread. */
/*==========================================================================*/
static void SentDecoderThread(void*) {
chRegSetThreadName("SEND RX");
while (true) {
msg_t ret;
msg_t msg;

View File

@ -2,12 +2,15 @@
#include "hal.h"
#include "chprintf.h"
#include "efifeatures.h"
#include "uart.h"
#include "io_pins.h"
#include "persistence.h"
#include "fault.h"
#include "pt2001impl.h"
#include "sent.h"
#include "can.h"
/**
* @brief Global variables
@ -26,7 +29,7 @@ extern bool isOverallHappyStatus;
extern mfs_error_t flashState;
extern int canWriteOk;
extern int canWriteNotOk;
extern Pt2001 chip;
extern Pt2001 chips[EFI_PT2001_CHIPS];
extern GDIConfiguration configuration;
static int counter = 0;
@ -34,27 +37,34 @@ static int counter = 0;
static THD_WORKING_AREA(waUartThread, 256);
static void UartThread(void*)
{
chRegSetThreadName("UART debug");
while (true) {
counter = (counter + 1) % 1000;
if (chip.fault != McFault::None) {
chprintf(chp, "FAULT fault=%d status=%x status2=%x 0x1A6=%x 0x1A7=%x 0x1A8=%x\r\n",
(int)chip.fault,
chip.status,
chip.status5,
chip.status6,
chip.status7,
chip.status8);
} else {
chprintf(chp, "%x %d %d HAPPY fault=%d status=%x status2=%x flash=%d %d CAN o/e %d %d\r\n",
configuration.inputCanID,
(int)(configuration.PumpPeakCurrent * 1000),
configuration.updateCounter,
(int)chip.fault,
chip.status,
chip.status5,
(int)flashState, counter,
canWriteOk, canWriteNotOk);
chprintf(chp, "Flash=%d %d CAN o/e %d %d\r\n",
(int)flashState, counter,
canWriteOk, canWriteNotOk);
for (size_t i = 0; i < EFI_PT2001_CHIPS; i++) {
if (chips[i].fault != McFault::None) {
chprintf(chp, "%d: FAULT fault=%d status=%x status2=%x 0x1A6=%x 0x1A7=%x 0x1A8=%x\r\n",
i,
(int)chips[i].fault,
chips[i].status,
chips[i].status5,
chips[i].status6,
chips[i].status7,
chips[i].status8);
} else {
chprintf(chp, "%d: 0x%03x %d %d HAPPY fault=%d status=%x status2=%x\r\n",
i,
canGetInputCanIdBase(i),
(int)(configuration.PumpPeakCurrent * 1000),
configuration.updateCounter,
(int)chips[i].fault,
chips[i].status,
chips[i].status5);
}
}
sentDebug();