From d1a746f4544309cdb7024f60b9f7158a1d53513c Mon Sep 17 00:00:00 2001 From: Frank Voorburg Date: Wed, 26 Jul 2017 11:08:53 +0000 Subject: [PATCH] Refs #316. Integrated XCP on CAN transport layer into the LibOpenBLT API. git-svn-id: https://svn.code.sf.net/p/openblt/code/trunk@314 5dc33758-31d5-4daf-9ae8-b24bf3d40d73 --- Host/Source/LibOpenBLT/openblt.c | 23 +++++++++++++++++++++++ Host/Source/LibOpenBLT/openblt.h | 2 +- Host/Source/LibOpenBLT/openblt.pas | 2 +- Host/Source/LibOpenBLT/xcptpcan.h | 2 +- Host/libopenblt.dll | Bin 98816 -> 99328 bytes 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/Host/Source/LibOpenBLT/openblt.c b/Host/Source/LibOpenBLT/openblt.c index 11c40d4e..a533cefd 100644 --- a/Host/Source/LibOpenBLT/openblt.c +++ b/Host/Source/LibOpenBLT/openblt.c @@ -39,6 +39,7 @@ #include "session.h" /* Communication session module */ #include "xcploader.h" /* XCP loader module */ #include "xcptpuart.h" /* XCP UART transport layer */ +#include "xcptpcan.h" /* XCP CAN transport layer */ /**************************************************************************************** @@ -165,6 +166,28 @@ LIBOPENBLT_EXPORT void BltSessionInit(uint32_t sessionType, xcpLoaderSettings.transport = XcpTpUartGetTransport(); } } + else if (transportType == BLT_TRANSPORT_XCP_V10_CAN) + { + /* Cast transport settings to the correct type. */ + tBltTransportSettingsXcpV10Can * bltTransportSettingsXcpV10CanPtr; + bltTransportSettingsXcpV10CanPtr = + (tBltTransportSettingsXcpV10Can * )transportSettings; + /* Convert transport settings to the format supported by the XCP CAN transport + * layer. It was made static to make sure it doesn't get out of scope when + * used in xcpLoaderSettings. + */ + static tXcpTpCanSettings xcpTpCanSettings; + xcpTpCanSettings.device = bltTransportSettingsXcpV10CanPtr->deviceName; + xcpTpCanSettings.channel = bltTransportSettingsXcpV10CanPtr->deviceChannel; + xcpTpCanSettings.baudrate = bltTransportSettingsXcpV10CanPtr->baudrate; + xcpTpCanSettings.transmitId = bltTransportSettingsXcpV10CanPtr->transmitId; + xcpTpCanSettings.receiveId = bltTransportSettingsXcpV10CanPtr->receiveId; + xcpTpCanSettings.useExtended = (bltTransportSettingsXcpV10CanPtr->useExtended != 0); + /* Store transport layer settings in the XCP loader settings. */ + xcpLoaderSettings.transportSettings = &xcpTpCanSettings; + /* Link the transport layer to the XCP loader settings. */ + xcpLoaderSettings.transport = XcpTpCanGetTransport(); + } /* Perform actual session initialization. */ SessionInit(XcpLoaderGetProtocol(), &xcpLoaderSettings); } diff --git a/Host/Source/LibOpenBLT/openblt.h b/Host/Source/LibOpenBLT/openblt.h index 854d8f46..467fe366 100644 --- a/Host/Source/LibOpenBLT/openblt.h +++ b/Host/Source/LibOpenBLT/openblt.h @@ -146,7 +146,7 @@ typedef struct t_blt_transport_settings_xcp_v10_rs232 */ typedef struct t_blt_transport_settings_xcp_v10_can { - char const * deviceName; /**< Device name such as can0. */ + char const * deviceName; /**< Device name such as can0, peak_pcanusb etc. */ uint32_t deviceChannel; /**< Channel on the device to use. */ uint32_t baudrate; /**< Communication speed in bits/sec. */ uint32_t transmitId; /**< Transmit CAN identifier. */ diff --git a/Host/Source/LibOpenBLT/openblt.pas b/Host/Source/LibOpenBLT/openblt.pas index d1a71194..3e56ea8e 100644 --- a/Host/Source/LibOpenBLT/openblt.pas +++ b/Host/Source/LibOpenBLT/openblt.pas @@ -93,7 +93,7 @@ type // Structure layout of the XCP version 1.0 CAN transport layer settings. tBltTransportSettingsXcpV10Can = record - deviceName: PAnsiChar; // Device name such as can0, pcanusb, etc. + deviceName: PAnsiChar; // Device name such as can0, peak_pcanusb, etc. deviceChannel: LongWord; // Channel on the device to use. baudrate: LongWord; // Communication speed in bits/sec. transmitId: LongWord; // Transmit CAN identifier. diff --git a/Host/Source/LibOpenBLT/xcptpcan.h b/Host/Source/LibOpenBLT/xcptpcan.h index e43c6ad0..86890335 100644 --- a/Host/Source/LibOpenBLT/xcptpcan.h +++ b/Host/Source/LibOpenBLT/xcptpcan.h @@ -45,7 +45,7 @@ extern "C" { */ typedef struct t_xcp_tp_can_settings { - char const * device; /**< Device name such as can0, pcanusb, etc. */ + char const * device; /**< Device name such as can0, peak_pcanusb, etc. */ uint32_t channel; /**< Channel on the device to use. */ uint32_t baudrate; /**< Communication speed in bits/sec. */ uint32_t transmitId; /**< Transmit CAN identifier. */ diff --git a/Host/libopenblt.dll b/Host/libopenblt.dll index b3cca9dda9fac75c85a136b2b9da086b6fdbfe8f..879470e2efebb350448aa1b22d8b1669c701cb3d 100644 GIT binary patch delta 11192 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
b#Ep-sLde=q+k2P;X+Qf0UDHmrg_mA-1Y zYE^kvRcEQW>Oys;TC2XO)|IOJ)DP8G9KLLVI1G@R9JH za6`BwOcWQ2#iB#p081Dz;4|Xq;#Z=l6d{$yND0y;sYF^W)kxc=|B^0AKS=i_Pq~jg zO3sp}$+Kkl%HA%&DF-PVAwRY&hn4r06Oa|GItCk_PY|bI-Zz=wFdsG_hYY^}xqZXj zZvNA(xAe7ySYj-c#cB~OBP`=AS(b&C#g?U(I!nD}kLAr$%X^kHmd`C;Sv=_|I-X9V zpP?P}W_mll7rZ)1H_;!{=O7clr~ePE25;*)>kR7|Yahm+34v;$GRe$xrjmJ`ImjGm zPBGsyH<(|T4kjGd#u!);)7kl~on6INvB%gJ_8c2#i?vO%Jqx+9#BqKK z+Yh#%Z62I~^XDSDM2_QBE`^)ME$6DZO!Lpkx} z`|=@tB$O0^Pv%qj$^0yS9>1GE!Jp#K@R`DNp%Aj@tk5CoMP3{#z9_yV?hp@&&EltG zn|N8gEB;a{c8ET(HU~&g!ulL46-%omhjc)?Abl%Mk_+X($#J>kQRfZ^|m5Iu9 zC08j>Rwxz9dS$b+OWC9BhvoXI^11T0a!vU``APXr>8bj{f(=xo)dbZ7NtdjqsOjot zSi1Ao=hb4hQgx^sp&aj0$23FoeXU+qe^l?`xhx}yIG9TvugT^E>Fy|kc&e6s&-OEhhT)vMCu>FM+=dM>?` zUPW(vX@3c6Dt*ej8p`@s>&w>t)(>DAe`Nj2dfD1(H9@R)2)l(=;k@vT5G&FUuPNe8 z(GGRkCEgZENe}fmRhlK`N$aG|(r#(L^pVsmU6F1`I+>Csd89lMcAyRNOY*L+T_`{a zRU(z~N~W?*se?e>RemXjqz!;V7O9ShLbgnczy+1q;QoJh0aOSTPDN31)G6~1WsJY$iL6&0*)U1?*C`oULXzvfJ4P_BHlR_6XYw1s-p5{A3)I02jp#D&;7Srz zg@aIKT7`j--YMc_FbotS4q|OoPDszjD{2~R#&SCP6=eopwLygL zaer_Cfw)wx6<-neK%h=RIle0TNr93eB}>z#0w@A2A;&LB_aqNFR9*(LLUMz=Pd+1m zE`J9*i=Q$`nFV|GE#;o#p&Hc?H4gTcA?jFI+^^$k9UzDtc=Ui3yqVfh`J2Pw{K1-) zG3Mds(Xf}yfDCq7Zd=0X7&?Kr&>XGMBk0j|DxFDBrDxK)^g`NBFQdyKh&A+!bRE5u b-bKHzRpg`eaX6ctp%1|aO^(M#%IE(Au}B;~