/iso14229

ISO 14229 (UDS) server and client for embedded systems

Primary LanguageCMIT LicenseMIT

iso14229

Build Status

简体中文

iso14229 is a UDS server and client implementation (ISO14229-1:2013) targeting embedded systems. It embeds the isotp-c ISO15765-2 (ISO-TP) transport layer.

API status: unstable

Features:

  • dependency injection gives you complete control
  • uses only static memory allocation
  • architecture-independent
    • tested: arm, x86-64, ppc
    • tests run under qemu
  • has many existing unit-tests and tests are easy to extend

supported functions (server and client )

SID name supported
0x10 diagnostic session control
0x11 ECU reset
0x14 clear diagnostic information
0x19 read DTC information
0x22 read data by identifier
0x23 read memory by address
0x24 read scaling data by identifier
0x27 security access
0x28 communication control
0x2A read periodic data by identifier
0x2C dynamically define data identifier
0x2E write data by identifier
0x2F input control by identifier
0x31 routine control
0x34 request download
0x35 request upload
0x36 transfer data
0x37 request transfer exit
0x38 request file transfer
0x3D write memory by address
0x3E tester present
0x83 access timing parameter
0x84 secured data transmission
0x85 control DTC setting
0x86 response on event

Documentation

Examples

examples/README.md

Tests

test_iso14229.c

Running Tests

make test

qemu

CC=powerpc-linux-gnu-gcc make test_bin
qemu-ppc -L /usr/powerpc-linux-gnu test_bin

wine

CC=x86_64-w64-mingw32-gcc make test_bin
wine test_bin.exe

Contributing

contributions are welcome

Acknowledgements

  • isotp which this project embeds

License

MIT

Changelog

0.0.0

  • initial release

0.1.0

  • Add client
  • Add server SID 0x27 SecurityAccess
  • API changes

0.2.0

  • removed all instances of __attribute__((packed))
  • refactored server download functional unit API to simplify testing
  • refactored tests
    • ordered by service
    • documented macros
  • removed middleware
  • simplified server routine control API
  • removed redundant function iso14229ServerEnableService
  • updated example

0.3.0

  • added iso14229ClientRunSequenceBlocking(...)
  • added server and client examples
  • simplified test flow, deleted opaque macros and switch statements
  • flattened client and server main structs
  • simplified usage by moving isotp-c initialization parameters into server/client config structs
  • remove redundant buffers in server

Design Docs

Client State Machine

@startuml
title 客户端请求状态机
note as N1
enum {
    kNoError=0,
    kErrBadRequest,
    kErrP2Timeout,
} ClientErr;

static inline bool isRequestComplete() {return state==Idle;}

while (Idle != client->state) {
    receiveCAN(client);
    Iso14229ClientPoll(client);
}
end note

state Idle
state Sending
state Sent
state SentAwaitResponse
state ProcessResponse
Idle: if (ISOTP_RET_OK == isotp_receive(...)) // Error
ProcessResponse: isotp_receive()
ProcessResponse: _ClientValidateResponse(...)
ProcessResponse: _ClientHandleResponse(...)

Sending --> Sent: 传输层完成传输 

Sent --> Idle : suppressPositiveResponse
Sending --> SentAwaitResponse: !suppressPositiveResponse
SentAwaitResponse -> Idle: 响应收到了 ||\np2 超时
SentAwaitResponse --> ProcessResponse : ISOTP_RECEIVE_STATUS_FULL == link->receive_status
ProcessResponse --> Idle

[*] -> Idle
Idle -> Sending : _SendRequest()

@enduml
@startuml
title Request Lifecycle
alt normal
    alt positive response
        client --> client: Sending
        client -> server : *Any* Service
        client --> client: SentAwaitResponse: set p2
        alt 0x78 requestCorrectlyReceived-ResponsePending
            server -> client : 0x3F 0x78 
            client -->server : txLink  idle
            client --> client: SentAwaitResponse: set p2star
        end
        server -> client : Positive Service Response
        client --> client: Idle 
    else negative response
        server -> client !! : Negative Service Response
        client --> client: Idle: RequestErrorNegativeResponse
    else SID mismatch
        server -> client !! : Mismatched Service Response
        client --> client: Idle: RequestErrorResponseSIDMismatch
    end
else unexpected response
    server -> client !! : Unexpected Response
    client --> client: Idle: RequestErrorUnsolicitedResponse
end
@enduml
@startuml
' !pragma useVerticalIf on
title 客户端请求流程
start

:clientSendRequest();
if (验证参数) then (对)
:ok;
else (不对)
:foo;
detach
endif

:clearRequestContext();
if (等待UDS访问) then (访问接收了,进入UDS会话)
else (时间超过<b>20ms)
@enduml

Server 0x78 requestCorrectlyReceived-ResponsePending

@startuml
client -> server : *Any* Service
server -> userServiceHandler: handler(args)
note right: Doing this will take a long time\nso I return 0x78
userServiceHandler -> server: 0x78
server -> client : 0x3F 0x78 
client -->server : txLink  idle
server -> userServiceHandler: handler(args)
note right: actually call the long-running service
... p2* > t > p2 ... 
userServiceHandler -> server : Service Response
server -> client : Service Response
@enduml
@startuml
' !pragma useVerticalIf on
title 0x78流程(写flash)
start

:BufferedWriterWrite(BufferedWriter *self, const uint8_t *ibuf, uint32_t size, bool RCRRP);

if (RCRRP) then (true)
:write to flash;
else (false)
endif
if (iBufIdx == size) then (true)
    :write to pageBuffer;
    :iBufIdx = 0;
    :return kBufferedWriterWritePending;
    :0x78 RCRRP;
    detach;
else (false)
    :memmove(pageBuffer + pageBufIdx, iBuf + iBufIdx, size - iBufIdx);
    :write to pageBuffer;
    :iBufIdx += size;
    :0x01 PositiveResponse;
    :0x78 RCRRP;
    detach
endif

@enduml