XCP on classic CAN — co se mění
Příklad sestavuje obraz pro CAN presetem DebugCan; vše v této kapitole je
to, co tento preset mění oproti Debug (obraz pro TCP popsaný v kapitole
Integrace: XCP on TCP). Periferie ST se
jmenuje FDCAN; SDK ji používá v režimu classic CAN (rámce 8 B, bez
přepínání bitové rychlosti) — dále jen classic CAN.
Stejné a odlišné
| Stejné jako u TCP | Odlišné na CAN |
|---|---|
zdroje enginu a qfw_xcp.h | kodek transportu přeložený do enginu: qfw_xcptl_can.c místo qfw_xcptl.c (volí QFW_XCP_TRANSPORT=can, bez rámcování na sběrnici, MAX_CTO = MAX_DTO = 8) |
| port hodin a kontrakt hodin | glue: glue/freertos_can/xcp_can_glue.c místo glue/freertos_lwip/xcp_sdk_glue.c |
identita (project_name, epk), log, kritická sekce, paměť fronty | port: port/fdcan (wrapper FDCAN) navíc k port/clock; lwIP není potřeba |
eventy: qfw_xcp_create_event / qfw_xcp_trigger_event, daqId v QInsight | konfigurace glue: tQfwXcpCanGlueConfig (master_id, slave_id, extended_ids, bitrate_kbps) místo port |
tři volání ve freertos.c | vstup pro příjem: qfw_xcp_rx_can_frame(data, dlc) místo qfw_xcp_rx(bytes, len) |
| pravidla pro proměnné a nástroje pro adresy | #if defined(QFW_XCP_TRANSPORT_CAN) v integračním souboru vybírá hlavičku a konfiguraci glue |
Jeden obraz firmwaru nese právě jeden transport (symboly obou variant enginu záměrně kolidují).
Volba sestavení
cmake --preset DebugCan nastaví QFW_XCP_TRANSPORT=can
(CMakePresets.json); ve vlastním projektu předejte při konfiguraci
-DQFW_XCP_TRANSPORT=can. Úryvek CMake z kapitoly o TCP pak přidá
${QFW_XCP_GLUE_FREERTOS_CAN_SOURCES}, ${QFW_XCP_PORT_FDCAN_SOURCES},
odpovídající include adresáře a definice QFW_XCP_TRANSPORT_CAN (pro váš
integrační soubor) a ${QFW_XCP_PORT_FDCAN_DEFINES}
(= HAL_FDCAN_MODULE_ENABLED).
Port FDCAN a váš projekt CubeMX
port/fdcan/fdcan_classic.c uvádí FDCAN1 do provozu kompletně v kódu:
kernel clock FDCAN z HSE (8 MHz na Nucleo, tabulka bit timingu je
spočítána pro něj), GPIO PD0 = FDCAN1_RX / PD1 = FDCAN1_TX (AF9), klasický
formát rámce, rozložení message RAM (RX FIFO0 hloubky 32, TX FIFO hloubky
16), jeden akceptační filtr propouštějící do RX FIFO0 pouze id mastera
(vše ostatní i všechny remote rámce odmítnuty), provoz pollingem bez
přerušení. API: FdcanClassic_Init(&cfg),
FdcanClassic_Receive(data, &dlc), FdcanClassic_Transmit(data, len),
FdcanClassic_RecoverBusOff(). Podporované bitové rychlosti: 125, 250,
500, 1000 kbit/s.
port/fdcan/hal/ obsahuje HAL driver FDCAN od ST (STM32Cube FW_H7
V1.13.0, beze změn, BSD-3-Clause, viz port/fdcan/ORIGIN.md). Příklad
FDCAN ve svém .ioc nezapíná: periferii uvádí do provozu výhradně
FdcanClassic_Init (hodiny, GPIO, filtr, message RAM) a HAL driver
pochází z port/fdcan/hal, protože CubeMX jej pro nezapnutou periferii do
Drivers/ nekopíruje. Ve svém projektu postupujte stejně: FDCAN v .ioc
nezapínejte, do cíle přidejte port/fdcan/fdcan_classic.c a
port/fdcan/hal/stm32h7xx_hal_fdcan.c s include adresáři a
HAL_FDCAN_MODULE_ENABLED (přesně to dělají proměnné
QFW_XCP_PORT_FDCAN_SOURCES, QFW_XCP_PORT_FDCAN_INCLUDE_DIRS,
QFW_XCP_PORT_FDCAN_DEFINES z cmake/qfw_xcp.cmake, viz CMakeLists.txt
příkladu). Toto je konfigurace ověřená na NUCLEO-H723ZG s QInsight.
Integrační soubor a glue
Větev CAN v app/xcp_server.c příkladu:
#if defined(QFW_XCP_TRANSPORT_CAN)
#include "xcp_can_glue.h"
#define QFW_XCP_CAN_MASTER_ID 0x200U /* QInsight default: master -> slave */
#define QFW_XCP_CAN_SLAVE_ID 0x201U /* slave -> master */
#define QFW_XCP_CAN_BITRATE_KBPS 500U
#endif
...
tQfwXcpCanGlueConfig config = {
.project_name = QFW_XCP_PROJECT_NAME,
.epk = QFW_XCP_EPK,
.master_id = QFW_XCP_CAN_MASTER_ID,
.slave_id = QFW_XCP_CAN_SLAVE_ID,
.extended_ids = false, /* 11-bit identifiers */
.bitrate_kbps = QFW_XCP_CAN_BITRATE_KBPS,
.log_level = 2U,
.get_clock_us = QfwXcpClockUs,
};
if (!QfwXcpCanGlue_Init(&config))
{
return false;
}
QfwXcpCanGlue_Init (glue/freertos_can/xcp_can_glue.c) vytvoří
rekurzivní mutex, inicializuje engine (3 segmenty fronty), zavolá
FdcanClassic_Init s rx_id = master_id, tx_id = slave_id a vytvoří
server task QfwXcpCanGlue (zásobník 4 KB, priorita idle+2). Smyčka úlohy
běží každou 1 ms:
drain RX FIFO0 -> qfw_xcp_rx_can_frame() per frame (one frame = one XCP packet, no framing)
qfw_xcp_poll() -> GlueTransmit -> FdcanClassic_Transmit (one call = one frame on slave_id, len 8, zero padded)
FdcanClassic_RecoverBusOff() true? -> qfw_xcp_on_transport_reset() (the only transport reset on CAN)
vTaskDelay(1)
Neexistuje spojení ani proud bajtů: poškozený rámec engine zahodí a nic se
nemusí znovu synchronizovat; plné TX FIFO je čistý backpressure
(transmit vrátí false, engine rámec zopakuje při příštím pollu). RX
FIFO hloubky 32 pojme více než 8 ms plně zatížené sběrnice 500 kbit/s,
kadence 1 ms má tedy rezervu.
Zapojení (NUCLEO-H723ZG)
FDCAN1 používá PD0 = FDCAN1_RX a PD1 = FDCAN1_TX (AF9). Nucleo nemá CAN transceiver — připojte externí 3,3V transceiver (např. SN65HVD230, TJA1051T/3): jeho TXD na PD1, RXD na PD0, VCC 3,3 V, společná GND, CANH/CANL na sběrnici se 120Ω zakončením na obou koncích kabelu (strana PCAN-USB obvykle jedno poskytuje).
Strana QInsight
Driver PEAK CAN Adapter
(PCAN-USB; bitrate=500000 (bit/s), deviceId = ID vašeho adaptéru),
protokol XCP on CAN s
masterId=0x200, slaveId=0x201, extendedIds=false. Proměnné, události
a daqId se konfigurují přesně jako u TCP. Hodnoty delší než jeden rámec
QInsight řetězí automaticky: čtení po nejvýše 7 B (SHORT_UPLOAD a dále
UPLOAD), zápis SET_MTA a pak DOWNLOAD po nejvýše 6 B — 8bajtová
hodnota se tak čte jako 7+1 B a zapisuje jako 6+2 B; se slavem s block
módem jde 8bajtová hodnota jedním UPLOAD burstem 7+1 B. Ukázkový projekt
Qenex_CAN_XCP_NucleoH723_Maps_FreeRTOS.qproj popisuje kapitola
XCP on CAN na NUCLEO-H723ZG.
Dimenzování a propustnost
- Vysílací fronta: 2–4 segmenty (
QFW_XCP_QUEUE_MEM_SIZE(3)= 4632 B je výchozí hodnota glue). CAN přenese nejvýše 6 datových bajtů na DAQ rámec při ~4000 rámcích/s (500 kbit/s, celá sběrnice) — větší fronta jen prohlubuje zpoždění, propustnost zvýšit nemůže. - Kapacita DAQ na rámec: identifikační pole má 2 bajty (číslo ODT +
DAQ); s časovými značkami slave (
daqTimestamps=slave) nese první ODT listu navíc časovou značku DWORD → 2 B dat v ODT0, 6 B v každém dalším ODT. SdaqTimestamps=masternesou všechny ODT 6 B. - Indikace ztráty: přetečení vysílací fronty (na CAN snadno dosažitelné ambiciózní sadou DAQ) se podle standardu XCP hlásí nastavením MSB čísla ODT v prvním DTO po přetečení — QInsight ztráty zobrazí; zahazují se celé rámce, data se nikdy nepoškodí.
- Neimplementováno (podle standardu volitelné, QInsight nepoužívá):
GET_SLAVE_ID,GET_DAQ_ID,SET_DAQ_ID(ERR_CMD_UNKNOWN).
Dále
Kontrakt enginu — pravidla, která za glue stojí; Řešení potíží — řádky pro CAN v tabulce příznaků.

