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

View File

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

View File

@ -10,6 +10,7 @@ class Pt2001 : public Pt2001Base {
public: public:
// returns true if init successful // returns true if init successful
bool init(); bool init();
bool init(SPIDriver *spi, const SPIConfig *cfg);
protected: protected:
void acquireBus() override { void acquireBus() override {
@ -19,14 +20,23 @@ protected:
} }
void select() override { void select() override {
/* Acquire ownership of the bus. */
spiAcquireBus(driver);
/* Setup transfer parameters. */
spiStart(driver, spiCfg);
/* Slave Select assertion. */
spiSelect(driver); spiSelect(driver);
} }
void deselect() override { void deselect() override {
/* Slave Select de-assertion. */
spiUnselect(driver); spiUnselect(driver);
/* Ownership release. */
spiReleaseBus(driver);
} }
bool errorOnUnexpectedFlag() override { bool errorOnUnexpectedFlag() override {
return false;
} }
uint16_t sendRecv(uint16_t tx) override { uint16_t sendRecv(uint16_t tx) override {
@ -141,4 +151,5 @@ protected:
private: private:
SPIDriver* driver; 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, "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 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, "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 #endif
GmPressureDebug(); GmPressureDebug();
} }
@ -249,6 +249,8 @@ void SENT_ISR_Handler(uint8_t channel, uint16_t clocks, uint8_t flags) {
/* Decoder thread. */ /* Decoder thread. */
/*==========================================================================*/ /*==========================================================================*/
static void SentDecoderThread(void*) { static void SentDecoderThread(void*) {
chRegSetThreadName("SEND RX");
while (true) { while (true) {
msg_t ret; msg_t ret;
msg_t msg; msg_t msg;

View File

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