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,8 +175,9 @@ void CanTxThread(void*)
continue; // we were told to be silent continue; // we were told to be silent
} }
for (size_t i = 0; i < EFI_PT2001_CHIPS; i++) {
// keep constant while sending whole banch of messages // keep constant while sending whole banch of messages
int outID = canGetOutputCanIdBase(); int outID = canGetOutputCanIdBase(i);
if (intTxCounter % (1000 / CAN_TX_PERIOD_MS) == 0) { if (intTxCounter % (1000 / CAN_TX_PERIOD_MS) == 0) {
sendOutConfiguration(outID); sendOutConfiguration(outID);
@ -181,10 +186,13 @@ void CanTxThread(void*)
sendOutVersion(outID); sendOutVersion(outID);
} }
SendSomething(outID); SendSomething(i, outID);
if (i == 0) {
sendOutSentData(outID); sendOutSentData(outID);
} }
}
}
} }
static int getInt(CANRxFrame *frame, int offset) { static int getInt(CANRxFrame *frame, int offset) {
@ -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,8 +234,16 @@ void CanRxThread(void*)
continue; continue;
} }
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; bool withNewValue = false;
int inputID = canGetInputCanIdBase(); int inputID = canGetInputCanIdBase(i);
// TODO: valudate DLC and IDE // TODO: valudate DLC and IDE
if (frame.EID == inputID) { if (frame.EID == inputID) {
ASSIGN_IF_CHANGED(configuration.BoostVoltage, getInt(&frame, 1)); ASSIGN_IF_CHANGED(configuration.BoostVoltage, getInt(&frame, 1));
@ -256,10 +267,11 @@ void CanRxThread(void*)
} }
if (withNewValue) { if (withNewValue) {
saveConfiguration(); saveConfiguration();
chip.restart(); chips[i].restart();
}
// if (writeCount > 0)
// uartStartSend(&UARTD1, writeCount, printBuffer);
} }
// 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,7 +26,8 @@ static void InitPins() {
bool isOverallHappyStatus = false; bool isOverallHappyStatus = false;
static const SPIConfig spiCfg = { static const SPIConfig spiCfg[EFI_PT2001_CHIPS] = {
{
.circular = false, .circular = false,
.end_cb = nullptr, .end_cb = nullptr,
.ssport = GPIOB, .ssport = GPIOB,
@ -34,6 +37,20 @@ static const SPIConfig spiCfg = {
SPI_CR1_MSTR | SPI_CR1_MSTR |
SPI_CR1_CPHA | SPI_CR1_BR_1 | SPI_CR1_SPE, 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,
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, (int)flashState, counter,
canWriteOk, canWriteNotOk); 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(); sentDebug();