Správa a ladění vestavěných systémů: CLI přes CAN s ISO-TP a nástrojem CANshell
Vývoj vestavěných systémů se často potýká s problémem omezených ladicích rozhraní. V situacích, kdy tradiční UART není k dispozici, ale jsou přítomny CAN sběrnice, vzniká potřeba alternativních metod vzdálené interakce. Tento článek popisuje přístup k implementaci rozhraní příkazového řádku (CLI) přes CAN sběrnici s využitím protokolu ISO-TP a specializovaného nástroje CANshell, který poskytuje plnohodnotné ladicí prostředí pro mikrokontroléry.
Výzva ladění bez UART
Klasické ladění vestavěných systémů se tradičně opírá o sériová rozhraní, jako je UART. V reálných projektech, zejména při vývoji specializovaných elektronických desek, však může UART buď chybět, nebo být vyhrazen pro jiné účely. V takových scénářích, kde je k dispozici mnoho CAN portů, vyvstává úkol využít CAN sběrnici pro přenos ladicích informací a řídicích příkazů.
Hlavní problémy spočívají v následujícím:
- Omezená velikost CAN paketů: Standardní CAN paket pojme pouze 8 bajtů dat. To je naprosto nedostatečné pro přenos dlouhých CLI příkazů, které mohou dosahovat 150 bajtů i více, stejně jako pro příjem objemných odpovědí a logů. Řešení tohoto problému vyžaduje použití protokolu schopného fragmentovat a skládat data z několika CAN paketů.
- Oddělení datových toků: Při vzdáleném ladění je často nutné současně pracovat s vlastním CLI ladicího nástroje a CLI vzdáleného zařízení (ECU). Je nezbytné efektivně oddělovat a zobrazovat tyto toky na jednom terminálu.
- Přesměrování logů: Vestavěný software obvykle vypisuje logy do UART nebo SWO. Pro použití CLI přes CAN je nutné zajistit mechanismus přesměrování těchto logů do vybraného CAN rozhraní přes ISO-TP.
Pro řešení těchto úkolů se navrhuje použít protokol ISO-TP (ISO 15765-2), který umožňuje přenášet zprávy libovolné délky přes CAN sběrnici, a vyvinout specializovaný konzolový nástroj CANshell pro PC.
Architektura řešení: ISO-TP a CANshell
Navržené řešení je založeno na kombinaci protokolu ISO-TP a nástroje CANshell. ISO-TP zajišťuje spolehlivý přenos velkých objemů dat přes CAN, zatímco CANshell funguje jako most mezi TCP klientem (například PuTTY nebo TeraTerm) a CAN sběrnicí.
Princip fungování:
- Na straně PC: Nástroj CANshell spustí TCP server a otevře TCP socket. Tento socket je na jedné straně spojen s protokolem ISO-TP a na druhé straně s TCP klientem. Parametry připojení (ISO-TP adresy, COM port, rychlost CAN) jsou nástroji předány prostřednictvím argumentů příkazového řádku, což umožňuje automatizovat proces pomocí skriptů.
- Na straně mikrokontroléru (ECU): Je implementován ISO-TP zásobník, který přijímá data z CAN sběrnice a předává je do parseru CLI příkazů. Pro výstup logů a odpovědí se používá mechanismus přesměrování, který umožňuje odesílat tato data zpět přes ISO-TP.
- Interakce: Když TCP klient odešle příkaz, CANshell jej zachytí, zapouzdří do ISO-TP paketů a odešle přes USB-CAN převodník do CAN sběrnice. Na mikrokontroléru ISO-TP zásobník pakety shromáždí a příkaz se dostane do CLI parseru. Odpovědi a logy z mikrokontroléru jsou obdobně zapouzdřeny do ISO-TP, přeneseny přes CAN sběrnici do CANshell, a poté do TCP klienta.
Realizace komponent a příklady kódu
Pro praktickou implementaci byl vybrán USB-CAN převodník USB2CANFD_V1 díky jeho dostupnosti a jednoduchosti interakce přes sériový COM port pomocí protokolu SLCAN. Jako cílová platforma byla použita vývojová deska JZ-F407VET6 se dvěma CAN porty.
TCP server na straně PC je implementován v čistém C s použitím funkcí WinSock2. To umožňuje maximální znovupoužitelnost komponent protokolu ISO-TP a FIFO front jak ve firmwaru mikrokontroléru, tak v aplikaci na PC.
Příjem dat na mikrokontroléru přes ISO-TP a jejich předání do CLI parseru vypadá následovně:
void iso_tp1_rx_done(n_indn_t* in_done){
LOG_DEBUG(ISO_TP,"ISO_TP1,%s",Iso15765_n_indn_ToStr(in_done));
if(N_OK==in_done->rslt){
#ifdef HAS_CLI
IsoTpHandle_t* Node=IsoTpGetNode(1);
if(Node) {
Node->target_id = in_done->n_ai.n_sa;
cli_process_data(Node->cli_num, in_done->msg, in_done->msg_sz);
memset(in_done->msg,0,I15765_MSG_SIZE);
}
#endif
}
}
Tento callback iso_tp1_rx_done je volán po dokončení příjmu kompletní ISO-TP zprávy. Extrahovaná data předává funkci cli_process_data k dalšímu zpracování.
Pro přesměrování logů z mikrokontroléru do ISO-TP se používá speciální příkaz tpw 1. Po jeho provedení začnou všechny logovací funkce (LOG_ERROR, LOG_INFO, LOG_DEBUG) zapisovat data do fronty TxFIFO, která je asociována s první instancí ISO-TP.
void iso_tp1_puts(void* stream_ptr, const char* str, int32_t len) {
IsoTpHandle_t* Node = IsoTpGetNode(1);
if(Node) {
if(str) {
if(len) {
bool res = fifo_push_array(&Node->TxFifo, (uint8_t*)str, (uint32_t)len);
if(!res) {
Node->error_cnt++;
}
}
}
}
}
void iso_tp1_putc(void* stream_ptr, char ch) {
IsoTpHandle_t* Node = IsoTpGetNode(1);
if(Node) {
bool res = fifo_push(&Node->TxFifo, (uint8_t)ch);
if(!res) {
Node->error_cnt++;
}
}
}
Funkce iso_tp1_puts a iso_tp1_putc umisťují znaky nebo řetězce do bufferu TxFifo, odkud budou odeslány přes ISO-TP.
Správa přenosu dat a synchronizace
Úloha IsoTpTx na mikrokontroléru je zodpovědná za extrakci dat z TxFifo a jejich odesílání přes ISO-TP, jakmile je automat protokolu připraven.
static bool iso15765_tx_next(IsoTpHandle_t* const Node) {
bool res = false;
res = iso15765_is_idle( &Node->instance);
if( res) {
uint32_t count = fifo_get_count(&Node->TxFifo);
if(0 < count) {
uint32_t txLen = 0;
n_req_t isoTpFrame={0};
isoTpFrame.fr_fmt=CBUS_FR_FRM_STD;
res = iso_tp_node_to_address_info( Node, &isoTpFrame.n_ai);
res = iso_tp_node_to_proto_ctrl_info( Node, &isoTpFrame.n_pci);
res = fifo_pull_array(&Node->TxFifo, isoTpFrame.msg, sizeof(isoTpFrame.msg), &txLen);
if(res) {
isoTpFrame.msg_sz = txLen;
n_rslt ret = iso15765_send(&Node->instance, &isoTpFrame);
res = iso15765_ret_to_res(ret);
}
}
}
return res;
}
bool iso_tp_tx_proc_one(uint8_t num) {
bool res = false;
IsoTpHandle_t* Node = IsoTpGetNode(num);
if(Node) {
LOG_PARN(ISO_TP, "IsoTp%u,ProcTx", num);
res = iso15765_tx_next(Node);
Node->spin++;
}
return res;
}
Tyto úryvky kódu ukazují logiku odesílání dat. Funkce iso15765_tx_next kontroluje, zda je ISO-TP transceiver volný, a pokud ano, extrahuje data z TxFifo a iniciuje odeslání.
Na straně PC, v nástroji CANshell, jsou data přijatá přes ISO-TP také umístěna do fronty, odkud jsou následně odeslána TCP klientovi.
bool can_shell_iso_tp_rx_data(uint8_t num,
uint8_t iso_num,
const uint8_t* const data,
uint16_t msg_sz) {
bool res = false;
if(data) {
if(msg_sz) {
SocketHandle_t * Socket = SocketGetNode(1);
if(Socket) {
res = fifo_push_array(&Socket->TxFifo, data, (uint32_t) msg_sz);
log_debug_res(CAN_SHELL, res, "SocketTxFiFoPush");
}
}
}
return res;
}
static bool iso_tp_rx_done(uint8_t iso_num, n_indn_t* in_done) {
bool res = false;
if(in_done) {
LOG_INFO(ISO_TP, "ISO_TP_%u,MoveDone:%s", iso_num, Iso15765_n_indn_ToStr(in_done));
res = iso15765_ret_to_res(in_done->rslt);
if(res) {
IsoTpHandle_t *Node = IsoTpGetNode(iso_num);
if(Node) {
Node->target_id = in_done->n_ai.n_sa;
Node->rx_done = true;
#ifdef HAS_CAN_SHELL
res = can_shell_iso_tp_rx_data(1, iso_num, in_done->msg, in_done->msg_sz);
#endif
}
}else{
LOG_ERROR(ISO_TP, "MoveErr,Ret,%u=%s", in_done->rslt,
Iso15765retToStr(in_done->rslt));
}
}
return res;
}
Tyto funkce jsou zodpovědné za příjem ISO-TP dat na straně PC a jejich přenos do bufferu určeného pro TCP socket.
Závěrečná fáze – přenos dat z TCP serveru k připojenému TCP klientovi (PuTTY, TeraTerm):
static bool socket_server_connected_tx_proc(SocketHandle_t *const Node) {
bool res = false;
uint32_t tx_len = fifo_get_count(&Node->TxFifo );
if(tx_len) {
uint8_t TxPart[150] = {0};
uint32_t tx_size = 0 ;
res= fifo_pull_array(&Node->TxFifo , TxPart, sizeof(TxPart), &tx_size);
if(res) {
int tx_done_cnt = send(Node->socket_remote, (char*) TxPart, (int) tx_size, 0 );
if(tx_done_cnt==tx_size) {
res = true;
} else {
res = false ;
int ret = 0;
ret = WSAGetLastError();
LOG_ERROR(LG_SOCKET_SERVER,
"SendFailedWithErrorCode,ErrCode:%d=%s",
ret, WSAErrorToStr(ret));
}
}
}
return res;
}
Tento kód demonstruje, jak jsou data z bufferu socketu odesílána klientovi pomocí funkce send z WinSock2.
Důležitým aspektem je synchronizace ISO-TP relací. Byly pozorovány situace, kdy se CANshell "zahltil" proudem dat, což vedlo ke ztrátě zpráv. Řešení spočívalo v časovém rozložení ISO-TP relací, aby obě instance protokolu měly čas se obnovit a zpracovat data.
Použití nástroje CANshell
Pro spuštění nástroje CANshell je nutné zadat řadu pozičních argumentů:
- COM port: Číslo COM portu, ke kterému je připojen USB-CAN převodník (například
COM3). - Přenosová rychlost CAN: Rychlost CAN sběrnice v kbit/s (například
500000pro 500 kbit/s). - ISO-TP adresa PC: Vlastní ISO-TP adresa nástroje CANshell v síti (například
0xC). - ISO-TP adresa cílového zařízení: ISO-TP adresa mikrokontroléru (ECU), se kterým je třeba navázat komunikaci (například
0xA). - TCP port: Číslo TCP portu, který CANshell otevře pro připojení klienta (například
50003).
Příklad spuštění nástroje:
CANshell.exe COM3 500000 0xC 0xA 50003
Po spuštění nástroj CANshell otevře dva terminály: jeden pro vlastní CLI a druhý pro CLI vzdáleného zařízení, ke kterému se lze připojit přes TCP klienta (PuTTY/TeraTerm) na zadaném TCP portu. Tímto způsobem získá ladič plnohodnotný přístup ke vzdálenému systému, simulující přímé UART připojení.
Co je důležité
- Řešení problému absence UART: Navržená metoda umožňuje organizovat plnohodnotné CLI pro ladění vestavěných systémů, i když na desce není tradiční UART, a to s využitím dostupných CAN sběrnic.
- Využití ISO-TP pro velká data: Protokol ISO-TP je kriticky důležitý pro přenos CLI příkazů a logů, protože umožňuje obejít omezení 8 bajtů na CAN paket tím, že fragmentuje a skládá zprávy.
- Nástroj CANshell jako most: Specializovaný nástroj CANshell na PC funguje jako efektivní prostředník mezi standardními TCP klienty (PuTTY, TeraTerm) a CAN sběrnicí, zajišťující transparentní přenos dat.
- Obousměrná komunikace a logování: Systém podporuje jak odesílání příkazů na ECU, tak příjem asynchronních logů a odpovědí, s možností přesměrování logů přímo do ISO-TP.
- Univerzálnost a škálovatelnost: Přístup je založen na standardních protokolech a široce dostupném hardwaru, což jej činí použitelným pro širokou škálu vestavěných projektů.
— Editorial Team
Zatím žádné komentáře.