big refactoring: J1939, log output, state machine bug fixes
This commit is contained in:
+427
-93
@@ -11,107 +11,272 @@
|
||||
#include "string.h"
|
||||
#include "can.h"
|
||||
#include "edcan.h"
|
||||
#include "debug.h"
|
||||
#include <string.h>
|
||||
|
||||
extern GBT_BCL_t GBT_ReqPower;
|
||||
extern GBT_BCL_t GBT_CurrPower;
|
||||
|
||||
j_receive_t j_rx;
|
||||
|
||||
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
|
||||
{
|
||||
CAN_RxHeaderTypeDef RxHeader;
|
||||
uint8_t RxData[8] = {0,};
|
||||
typedef struct{
|
||||
uint8_t data[256];
|
||||
uint32_t PGN;
|
||||
uint16_t size;
|
||||
uint8_t packets;
|
||||
uint8_t next_packet;
|
||||
uint8_t step;
|
||||
uint8_t state; // 0=idle, 1=wait CTS, 2=wait ACK
|
||||
uint32_t tick;
|
||||
}j_transmit_t;
|
||||
|
||||
if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK)
|
||||
{
|
||||
if((RxHeader.ExtId & 0x00FFFF) == ((J_ID_EV << 8) | J_ID_SE)){ // SA, DA match
|
||||
switch ((RxHeader.ExtId>>8) & 0x00FF00){
|
||||
static j_transmit_t j_tx;
|
||||
|
||||
case 0xEC00: //PGN Connection Management Message
|
||||
if(RxData[0] == 16){ //Request to Send
|
||||
/* Set the RTS values */
|
||||
j_rx.size = RxData[1] | (RxData[2]<<8);
|
||||
j_rx.packet = 1;
|
||||
j_rx.packets = RxData[3];
|
||||
j_rx.step = 2; //TODO
|
||||
j_rx.step_cts_remain = j_rx.step;
|
||||
j_rx.PGN = (RxData[7] << 16) | (RxData[6] << 8) | RxData[5];
|
||||
if(j_rx.size<256) { //TODO: valid check
|
||||
J_SendCTS(j_rx);
|
||||
j_rx.state = 1;
|
||||
}
|
||||
}
|
||||
if(RxData[0] == 255){ //Connection Abort
|
||||
j_rx.state = 0;
|
||||
}
|
||||
#define J1939_BUFFER_SIZE 64U
|
||||
|
||||
//if(RxData[0] == 32){}//Broadcast Announce Message
|
||||
/*
|
||||
* 1CEC56F4 10 31 00 07 07 00 02 00
|
||||
* 1CECF456 11 02 01 FF FF 00 02 00
|
||||
* 1CEB56F4 01 01 01 00 03 46 05 40
|
||||
* 1CEC56F4 FF FF FF FF FF 00 00 00
|
||||
*/
|
||||
typedef struct {
|
||||
j1939_rx_frame_t buffer[J1939_BUFFER_SIZE];
|
||||
uint16_t head;
|
||||
uint16_t tail;
|
||||
uint16_t count;
|
||||
uint32_t overflow;
|
||||
} j1939_rx_ring_t;
|
||||
|
||||
break;
|
||||
typedef struct {
|
||||
j1939_tx_frame_t buffer[J1939_BUFFER_SIZE];
|
||||
uint16_t head;
|
||||
uint16_t tail;
|
||||
uint16_t count;
|
||||
uint8_t busy;
|
||||
uint32_t overflow;
|
||||
} j1939_tx_ring_t;
|
||||
|
||||
case 0xEB00: //PGN Data Message
|
||||
if(j_rx.state != 1) break;
|
||||
if((RxData[0]>0) && (RxData[0]<35)){ //Array limit check
|
||||
if(j_rx.packet == RxData[0]){ //step check
|
||||
memcpy (&j_rx.data[(RxData[0]-1)*7], &RxData[1],7);
|
||||
j_rx.packet++;
|
||||
if(j_rx.packet > j_rx.packets){
|
||||
//End of transmission
|
||||
J_SendACK(j_rx);
|
||||
static j1939_rx_ring_t j_rxbuf;
|
||||
static j1939_tx_ring_t j_txbuf;
|
||||
static uint32_t j_tx_watchdog_last_log_tick;
|
||||
|
||||
j_rx.state = 2;
|
||||
}else{
|
||||
if(j_rx.step_cts_remain > 0) j_rx.step_cts_remain--;
|
||||
if(j_rx.step_cts_remain == 0){
|
||||
J_SendCTS(j_rx);
|
||||
j_rx.step_cts_remain = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
#define J1939_CRITICAL_ENTER() __disable_irq()
|
||||
#define J1939_CRITICAL_EXIT() __enable_irq()
|
||||
|
||||
case 0x1E00: //PGN BEM (ERROR)
|
||||
//Error force stop
|
||||
// --> Suspend EV
|
||||
EDCAN_printf(LOG_WARN, "BEM Received, force stopping...\n");
|
||||
EDCAN_printf(LOG_WARN, "BEM: %02X %02X %02X %02X", RxData[0], RxData[1], RxData[2], RxData[3]);
|
||||
EDCAN_printf(LOG_WARN, " %02X %02X %02X %02X\n", RxData[4], RxData[5], RxData[6], RxData[7]);
|
||||
GBT_ForceStop();
|
||||
break;
|
||||
static void J_SendTpRts(void);
|
||||
static void J_SendTpDtRange(uint8_t start_packet, uint8_t count);
|
||||
static void J_TxCheckTimeout(void);
|
||||
static void J_TxReset(void);
|
||||
static void J1939_ProcessRxFrame(const j1939_rx_frame_t *frame);
|
||||
static void J1939_RxBufferAdd(const j1939_rx_frame_t *frame);
|
||||
static uint8_t J1939_RxBufferGet(j1939_rx_frame_t *frame);
|
||||
static void J1939_TxBufferAdd(const j1939_tx_frame_t *frame);
|
||||
static uint8_t J1939_TxBufferPeek(j1939_tx_frame_t *frame);
|
||||
static void J1939_TxBufferDropFirst(void);
|
||||
static void J1939_TxQueueByPgn(uint32_t PGN, uint8_t pri, uint8_t DLC, const uint8_t *data, uint8_t pad_ff);
|
||||
|
||||
case 0x1900: //PGN BST (STOP)
|
||||
//Normal stop
|
||||
#define J1939_TP_CTS_WAIT_TIMEOUT_MS 1000U
|
||||
#define J1939_TP_ACK_WAIT_TIMEOUT_MS 1000U
|
||||
|
||||
// --> Suspend EV
|
||||
EDCAN_printf(LOG_WARN, "BST Received, stopping...\n");
|
||||
EDCAN_printf(LOG_WARN, "BST: %02X %02X %02X %02X", RxData[0], RxData[1], RxData[2], RxData[3]);
|
||||
EDCAN_printf(LOG_WARN, " %02X %02X %02X %02X\n", RxData[4], RxData[5], RxData[6], RxData[7]);
|
||||
GBT_StopEV(GBT_CST_BMS_ACTIVELY_SUSPENDS);
|
||||
static void J_TxReset(void){
|
||||
if(j_tx.state != 0){
|
||||
log_printf(LOG_WARN, "J1939 chunk send failed: TX session reset (state=%u pgn=0x%lX next=%u/%u)\n",
|
||||
j_tx.state, j_tx.PGN, j_tx.next_packet, j_tx.packets);
|
||||
}
|
||||
memset(&j_tx, 0, sizeof(j_tx));
|
||||
}
|
||||
|
||||
break;
|
||||
void J1939_InitBuffers(void){
|
||||
memset(&j_rxbuf, 0, sizeof(j_rxbuf));
|
||||
memset(&j_txbuf, 0, sizeof(j_txbuf));
|
||||
j_tx_watchdog_last_log_tick = 0U;
|
||||
J_TxReset();
|
||||
}
|
||||
|
||||
default:
|
||||
if(j_rx.state == 0){//TODO protections
|
||||
//Short packet
|
||||
j_rx.size = RxHeader.DLC;
|
||||
j_rx.packet = 1;
|
||||
j_rx.packets = 1;
|
||||
j_rx.step = 1;
|
||||
j_rx.step_cts_remain = 0;
|
||||
j_rx.PGN = (RxHeader.ExtId>>8) & 0x00FF00;
|
||||
j_rx.state = 2;
|
||||
memcpy (j_rx.data, RxData, j_rx.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uint16_t J1939_GetRxBufferCount(void){
|
||||
uint16_t c;
|
||||
J1939_CRITICAL_ENTER();
|
||||
c = j_rxbuf.count;
|
||||
J1939_CRITICAL_EXIT();
|
||||
return c;
|
||||
}
|
||||
|
||||
uint16_t J1939_GetTxBufferCount(void){
|
||||
uint16_t c;
|
||||
J1939_CRITICAL_ENTER();
|
||||
c = j_txbuf.count;
|
||||
J1939_CRITICAL_EXIT();
|
||||
return c;
|
||||
}
|
||||
|
||||
uint32_t J1939_GetRxOverflowCount(void){
|
||||
return j_rxbuf.overflow;
|
||||
}
|
||||
|
||||
uint32_t J1939_GetTxOverflowCount(void){
|
||||
return j_txbuf.overflow;
|
||||
}
|
||||
|
||||
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan){
|
||||
j1939_rx_frame_t frame;
|
||||
CAN_RxHeaderTypeDef rx_header;
|
||||
uint8_t rx_data[8] = {0};
|
||||
|
||||
if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data) != HAL_OK) return;
|
||||
|
||||
frame.ExtId = rx_header.ExtId;
|
||||
frame.DLC = rx_header.DLC;
|
||||
frame.tick = HAL_GetTick();
|
||||
memcpy(frame.data, rx_data, sizeof(frame.data));
|
||||
J1939_RxBufferAdd(&frame);
|
||||
}
|
||||
|
||||
static void J1939_ProcessRxFrame(const j1939_rx_frame_t *frame){
|
||||
uint32_t pgn;
|
||||
|
||||
if((frame->ExtId & 0x00FFFF) != ((J_ID_EV << 8) | J_ID_SE)) return; // SA, DA match
|
||||
|
||||
switch ((frame->ExtId >> 8) & 0x00FF00){
|
||||
case 0xEC00:
|
||||
if(frame->data[0] == 16){ // RTS
|
||||
j_rx.size = frame->data[1] | (frame->data[2] << 8);
|
||||
j_rx.packet = 1;
|
||||
j_rx.packets = frame->data[3];
|
||||
j_rx.step = 2;
|
||||
j_rx.step_cts_remain = j_rx.step;
|
||||
j_rx.PGN = (frame->data[7] << 16) | (frame->data[6] << 8) | frame->data[5];
|
||||
if(j_rx.size < 256){
|
||||
J_SendCTS(j_rx);
|
||||
j_rx.state = 1;
|
||||
}
|
||||
}
|
||||
if(frame->data[0] == 17){ // CTS
|
||||
pgn = (frame->data[7] << 16) | (frame->data[6] << 8) | frame->data[5];
|
||||
if((j_tx.state == 1) && (pgn == j_tx.PGN)){
|
||||
uint8_t req_count = frame->data[1];
|
||||
uint8_t req_start_packet = frame->data[2];
|
||||
log_printf(LOG_DEBUG, "J1939 event: TP CTS received (pgn=0x%lX cnt=%u start=%u exp=%u)\n",
|
||||
pgn, req_count, req_start_packet, j_tx.next_packet);
|
||||
if(req_count == 0){
|
||||
log_printf(LOG_DEBUG, "J1939 event: TP CTS wait (pgn=0x%lX)\n", j_tx.PGN);
|
||||
}else{
|
||||
j_tx.tick = frame->tick;
|
||||
J_SendTpDtRange(req_start_packet, req_count);
|
||||
}
|
||||
}else{
|
||||
log_printf(LOG_WARN, "J1939 chunk send failed: CTS ignored (tx_state=%u tx_pgn=0x%lX rx_pgn=0x%lX)\n",
|
||||
j_tx.state, j_tx.PGN, pgn);
|
||||
}
|
||||
}
|
||||
if(frame->data[0] == 19){ // ACK
|
||||
pgn = (frame->data[7] << 16) | (frame->data[6] << 8) | frame->data[5];
|
||||
if((j_tx.state == 2) && (pgn == j_tx.PGN)){
|
||||
log_printf(LOG_DEBUG, "J1939 event: TP ACK received, TX complete (pgn=0x%lX)\n", pgn);
|
||||
j_tx.state = 0;
|
||||
}
|
||||
}
|
||||
if(frame->data[0] == 255){
|
||||
j_rx.state = 0;
|
||||
J_TxReset();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xEB00:
|
||||
if(j_rx.state != 1) return;
|
||||
if((frame->data[0] > 0) && (frame->data[0] < 35) && (j_rx.packet == frame->data[0])){
|
||||
memcpy(&j_rx.data[(frame->data[0]-1)*7], &frame->data[1], 7);
|
||||
j_rx.packet++;
|
||||
if(j_rx.packet > j_rx.packets){
|
||||
J_SendACK(j_rx);
|
||||
j_rx.state = 2;
|
||||
}else{
|
||||
if(j_rx.step_cts_remain > 0) j_rx.step_cts_remain--;
|
||||
if(j_rx.step_cts_remain == 0){
|
||||
J_SendCTS(j_rx);
|
||||
j_rx.step_cts_remain = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1E00:
|
||||
log_printf(LOG_WARN, "J1939 fault received: BEM, forcing stop (data=%02X %02X %02X %02X %02X %02X %02X %02X)\n",
|
||||
frame->data[0], frame->data[1], frame->data[2], frame->data[3],
|
||||
frame->data[4], frame->data[5], frame->data[6], frame->data[7]);
|
||||
GBT_ForceStop();
|
||||
break;
|
||||
|
||||
case 0x1900:
|
||||
/* Repeated BST frames during STOP flow are normal on the bus.
|
||||
* Handle/log only once to avoid flooding UART logs.
|
||||
*/
|
||||
if((GBT_State != GBT_STOP) && (GBT_State != GBT_STOP_CSD) && (GBT_State != GBT_COMPLETE)){
|
||||
log_printf(LOG_DEBUG, "J1939 event: BST received, initiating stop flow (data=%02X %02X %02X %02X %02X %02X %02X %02X)\n",
|
||||
frame->data[0], frame->data[1], frame->data[2], frame->data[3],
|
||||
frame->data[4], frame->data[5], frame->data[6], frame->data[7]);
|
||||
GBT_StopEV(GBT_CST_BMS_ACTIVELY_SUSPENDS);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if(j_rx.state == 0){
|
||||
j_rx.size = frame->DLC;
|
||||
j_rx.packet = 1;
|
||||
j_rx.packets = 1;
|
||||
j_rx.step = 1;
|
||||
j_rx.step_cts_remain = 0;
|
||||
j_rx.PGN = (frame->ExtId >> 8) & 0x00FF00;
|
||||
j_rx.state = 2;
|
||||
memcpy(j_rx.data, frame->data, j_rx.size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void J1939_ExchangeRxBuffer(void){
|
||||
j1939_rx_frame_t frame;
|
||||
J_TxCheckTimeout();
|
||||
if(J1939_RxBufferGet(&frame)){
|
||||
J1939_ProcessRxFrame(&frame);
|
||||
}
|
||||
}
|
||||
|
||||
void J1939_ExchangeTxBuffer(void){
|
||||
j1939_tx_frame_t frame;
|
||||
CAN_TxHeaderTypeDef tx_header;
|
||||
uint32_t tx_mailbox;
|
||||
HAL_StatusTypeDef tx_status;
|
||||
|
||||
if(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) == 0) return;
|
||||
|
||||
/* Atomically reserve first queued frame without holding IRQ over HAL call */
|
||||
J1939_CRITICAL_ENTER();
|
||||
if(j_txbuf.busy || (j_txbuf.count == 0U)){
|
||||
J1939_CRITICAL_EXIT();
|
||||
return;
|
||||
}
|
||||
j_txbuf.busy = 1U;
|
||||
frame = j_txbuf.buffer[j_txbuf.tail];
|
||||
J1939_CRITICAL_EXIT();
|
||||
|
||||
tx_header.ExtId = frame.ExtId;
|
||||
tx_header.RTR = CAN_RTR_DATA;
|
||||
tx_header.IDE = CAN_ID_EXT;
|
||||
tx_header.DLC = frame.DLC;
|
||||
|
||||
tx_status = HAL_CAN_AddTxMessage(&hcan1, &tx_header, frame.data, &tx_mailbox);
|
||||
|
||||
J1939_CRITICAL_ENTER();
|
||||
if((tx_status == HAL_OK) && (j_txbuf.count > 0U)){
|
||||
j_txbuf.tail = (j_txbuf.tail + 1U) % J1939_BUFFER_SIZE;
|
||||
j_txbuf.count--;
|
||||
}
|
||||
j_txbuf.busy = 0U;
|
||||
J1939_CRITICAL_EXIT();
|
||||
|
||||
if(tx_status != HAL_OK){
|
||||
log_printf(LOG_WARN, "J1939 send failed: CAN TX error (st=%d extid=0x%lX dlc=%u free_mb=%lu err=0x%lX)\n",
|
||||
(int)tx_status, frame.ExtId, frame.DLC, HAL_CAN_GetTxMailboxesFreeLevel(&hcan1), HAL_CAN_GetError(&hcan1));
|
||||
if((tx_status == HAL_ERROR) && (HAL_CAN_GetError(&hcan1) & HAL_CAN_ERROR_NOT_INITIALIZED)){
|
||||
log_printf(LOG_WARN, "J1939 send failed: CAN not initialized, reinitializing\n");
|
||||
GBT_CAN_ReInit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GBT_CAN_ReInit(){
|
||||
@@ -120,24 +285,119 @@ void GBT_CAN_ReInit(){
|
||||
HAL_CAN_Start(&hcan1);
|
||||
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
|
||||
GBT_CAN_FilterInit();
|
||||
J1939_InitBuffers();
|
||||
}
|
||||
|
||||
void J_SendPacket(uint32_t PGN, uint8_t pri, uint8_t DLC, uint8_t *data){
|
||||
J_TxCheckTimeout();
|
||||
|
||||
CAN_TxHeaderTypeDef tx_header;
|
||||
uint32_t tx_mailbox;
|
||||
if(DLC > 8){
|
||||
/* Transport protocol for multi-packet payloads */
|
||||
if(DLC > sizeof(j_tx.data)) return;
|
||||
if(j_tx.state != 0){
|
||||
log_printf(LOG_WARN, "J1939 chunk send failed: TX busy (state=%u req_pgn=0x%lX cur_pgn=0x%lX)\n",
|
||||
j_tx.state, PGN, j_tx.PGN);
|
||||
return;
|
||||
}
|
||||
|
||||
tx_header.ExtId = (pri << 26) | (PGN << 8) | (J_ID_SE << 8) | J_ID_EV;
|
||||
tx_header.RTR = CAN_RTR_DATA;
|
||||
tx_header.IDE = CAN_ID_EXT;
|
||||
tx_header.DLC = DLC;
|
||||
memset(&j_tx, 0, sizeof(j_tx));
|
||||
memcpy(j_tx.data, data, DLC);
|
||||
j_tx.PGN = PGN;
|
||||
j_tx.size = DLC;
|
||||
j_tx.packets = (DLC + 6) / 7;
|
||||
j_tx.next_packet = 1;
|
||||
j_tx.step = 2;
|
||||
j_tx.state = 1;
|
||||
j_tx.tick = HAL_GetTick();
|
||||
log_printf(LOG_DEBUG, "J1939 event: TP RTS sent (pgn=0x%lX size=%u packets=%u)\n",
|
||||
j_tx.PGN, j_tx.size, j_tx.packets);
|
||||
|
||||
//TODO buffer wait
|
||||
HAL_CAN_AddTxMessage(&hcan1, &tx_header, data, &tx_mailbox);
|
||||
//HAL_Delay(2);
|
||||
J_SendTpRts();
|
||||
return;
|
||||
}
|
||||
J1939_TxQueueByPgn(PGN, pri, DLC, data, 1);
|
||||
|
||||
}
|
||||
|
||||
static void J_TxCheckTimeout(void){
|
||||
if(j_tx.state != 0){
|
||||
uint32_t now = HAL_GetTick();
|
||||
if((now - j_tx_watchdog_last_log_tick) >= 500U){
|
||||
log_printf(LOG_DEBUG, "J1939 event: TP TX watchdog (state=%u pgn=0x%lX next=%u/%u age=%lu)\n",
|
||||
j_tx.state, j_tx.PGN, j_tx.next_packet, j_tx.packets, (now - j_tx.tick));
|
||||
j_tx_watchdog_last_log_tick = now;
|
||||
}
|
||||
}else{
|
||||
j_tx_watchdog_last_log_tick = HAL_GetTick();
|
||||
}
|
||||
|
||||
if((j_tx.state == 1) && ((HAL_GetTick() - j_tx.tick) > J1939_TP_CTS_WAIT_TIMEOUT_MS)){
|
||||
log_printf(LOG_WARN, "J1939 chunk send failed: CTS timeout (pgn=0x%lX), resetting TX session\n", j_tx.PGN);
|
||||
J_TxReset();
|
||||
}else if((j_tx.state == 2) && ((HAL_GetTick() - j_tx.tick) > J1939_TP_ACK_WAIT_TIMEOUT_MS)){
|
||||
log_printf(LOG_WARN, "J1939 chunk send failed: ACK timeout (pgn=0x%lX), resetting TX session\n", j_tx.PGN);
|
||||
J_TxReset();
|
||||
}
|
||||
}
|
||||
|
||||
static void J_SendTpRts(void){
|
||||
uint8_t data[8];
|
||||
|
||||
data[0] = 16; // CONTROL_BYTE_TP_CM_RTS
|
||||
data[1] = j_tx.size & 0xFF;
|
||||
data[2] = j_tx.size >> 8;
|
||||
data[3] = j_tx.packets;
|
||||
data[4] = j_tx.step; // max packets before next CTS
|
||||
data[5] = j_tx.PGN;
|
||||
data[6] = j_tx.PGN >> 8;
|
||||
data[7] = j_tx.PGN >> 16;
|
||||
|
||||
J1939_TxQueueByPgn(0x00EC00, 7, 8, data, 0);
|
||||
}
|
||||
|
||||
static void J_SendTpDtRange(uint8_t start_packet, uint8_t count){
|
||||
uint8_t dt[8];
|
||||
uint8_t packet;
|
||||
uint8_t i;
|
||||
uint16_t idx;
|
||||
|
||||
if(j_tx.state != 1){
|
||||
log_printf(LOG_WARN, "J1939 chunk send failed: TP DT ignored (invalid TX state=%u)\n", j_tx.state);
|
||||
return;
|
||||
}
|
||||
|
||||
if((start_packet == 0) || (start_packet > j_tx.packets)) return;
|
||||
if(count == 0) return;
|
||||
if(start_packet != j_tx.next_packet){
|
||||
log_printf(LOG_WARN, "J1939 chunk send failed: TP desync (start=%u expected=%u), resetting TX session\n", start_packet, j_tx.next_packet);
|
||||
J_TxReset();
|
||||
return;
|
||||
}
|
||||
if((start_packet + count - 1) > j_tx.packets){
|
||||
count = j_tx.packets - start_packet + 1;
|
||||
}
|
||||
|
||||
for(packet = 0; packet < count; packet++){
|
||||
uint8_t seq = start_packet + packet;
|
||||
dt[0] = seq;
|
||||
idx = (uint16_t)(seq - 1) * 7;
|
||||
for(i = 0; i < 7; i++){
|
||||
if((idx + i) < j_tx.size) dt[i + 1] = j_tx.data[idx + i];
|
||||
else dt[i + 1] = 0xFF;
|
||||
}
|
||||
J1939_TxQueueByPgn(0x00EB00, 7, 8, dt, 0);
|
||||
}
|
||||
log_printf(LOG_DEBUG, "J1939 event: TP DT sent (pgn=0x%lX start=%u cnt=%u)\n", j_tx.PGN, start_packet, count);
|
||||
|
||||
j_tx.next_packet = start_packet + count;
|
||||
j_tx.tick = HAL_GetTick();
|
||||
if(j_tx.next_packet > j_tx.packets){
|
||||
j_tx.state = 2; // wait ACK
|
||||
}else{
|
||||
j_tx.state = 1; // wait next CTS
|
||||
}
|
||||
}
|
||||
|
||||
//void J_SendPacketLong(){
|
||||
// //TODO (no need)
|
||||
//}
|
||||
@@ -195,3 +455,77 @@ void GBT_CAN_FilterInit(){
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void J1939_RxBufferAdd(const j1939_rx_frame_t *frame){
|
||||
J1939_CRITICAL_ENTER();
|
||||
j_rxbuf.buffer[j_rxbuf.head] = *frame;
|
||||
j_rxbuf.head = (j_rxbuf.head + 1U) % J1939_BUFFER_SIZE;
|
||||
if(j_rxbuf.count == J1939_BUFFER_SIZE){
|
||||
j_rxbuf.tail = (j_rxbuf.tail + 1U) % J1939_BUFFER_SIZE;
|
||||
j_rxbuf.overflow++;
|
||||
log_printf(LOG_WARN, "J1939 RX buffer overflow: dropped oldest frame, overflow_count=%lu\n", j_rxbuf.overflow);
|
||||
}else{
|
||||
j_rxbuf.count++;
|
||||
}
|
||||
J1939_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
static uint8_t J1939_RxBufferGet(j1939_rx_frame_t *frame){
|
||||
uint8_t ok = 0;
|
||||
J1939_CRITICAL_ENTER();
|
||||
if(j_rxbuf.count > 0){
|
||||
*frame = j_rxbuf.buffer[j_rxbuf.tail];
|
||||
j_rxbuf.tail = (j_rxbuf.tail + 1U) % J1939_BUFFER_SIZE;
|
||||
j_rxbuf.count--;
|
||||
ok = 1;
|
||||
}
|
||||
J1939_CRITICAL_EXIT();
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void J1939_TxBufferAdd(const j1939_tx_frame_t *frame){
|
||||
J1939_CRITICAL_ENTER();
|
||||
j_txbuf.buffer[j_txbuf.head] = *frame;
|
||||
j_txbuf.head = (j_txbuf.head + 1U) % J1939_BUFFER_SIZE;
|
||||
if(j_txbuf.count == J1939_BUFFER_SIZE){
|
||||
j_txbuf.tail = (j_txbuf.tail + 1U) % J1939_BUFFER_SIZE;
|
||||
j_txbuf.overflow++;
|
||||
log_printf(LOG_WARN, "J1939 TX buffer overflow: dropped oldest frame, overflow_count=%lu\n", j_txbuf.overflow);
|
||||
}else{
|
||||
j_txbuf.count++;
|
||||
}
|
||||
J1939_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
static uint8_t J1939_TxBufferPeek(j1939_tx_frame_t *frame){
|
||||
uint8_t ok = 0;
|
||||
J1939_CRITICAL_ENTER();
|
||||
if(j_txbuf.count > 0){
|
||||
*frame = j_txbuf.buffer[j_txbuf.tail];
|
||||
ok = 1;
|
||||
}
|
||||
J1939_CRITICAL_EXIT();
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void J1939_TxBufferDropFirst(void){
|
||||
J1939_CRITICAL_ENTER();
|
||||
if(j_txbuf.count > 0){
|
||||
j_txbuf.tail = (j_txbuf.tail + 1U) % J1939_BUFFER_SIZE;
|
||||
j_txbuf.count--;
|
||||
}
|
||||
J1939_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
static void J1939_TxQueueByPgn(uint32_t PGN, uint8_t pri, uint8_t DLC, const uint8_t *data, uint8_t pad_ff){
|
||||
j1939_tx_frame_t frame;
|
||||
uint8_t i;
|
||||
|
||||
frame.ExtId = (pri << 26) | (PGN << 8) | (J_ID_SE << 8) | J_ID_EV;
|
||||
frame.DLC = DLC;
|
||||
for(i = 0; i < 8; i++){
|
||||
if(i < DLC) frame.data[i] = data[i];
|
||||
else frame.data[i] = pad_ff ? 0xFF : 0x00;
|
||||
}
|
||||
J1939_TxBufferAdd(&frame);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user