Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
Software for White Rabbit PTP Core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
32
Issues
32
List
Board
Labels
Milestones
Merge Requests
4
Merge Requests
4
CI / CD
CI / CD
Pipelines
Schedules
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
Software for White Rabbit PTP Core
Commits
0d6df9e0
Commit
0d6df9e0
authored
Nov 18, 2020
by
Tomasz Wlostowski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lib: UART control protocol, initial commit
parent
1e05cb70
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
538 additions
and
0 deletions
+538
-0
ertm14-uart-link.c
lib/ertm14-uart-link.c
+489
-0
ertm14-uart-link.h
lib/ertm14-uart-link.h
+49
-0
No files found.
lib/ertm14-uart-link.c
0 → 100644
View file @
0d6df9e0
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/errno.h>
#include <string.h>
#ifdef __linux__
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <asm/ioctls.h>
#include <termios.h>
#include <fcntl.h>
#endif
#ifdef CONFIG_TARGET_ERTM14
#include "dev/console.h"
#include "dev/simple_uart.h"
#endif
#include "ertm14-uart-link.h"
#ifndef DEBUG
#define ulink_dbg(...)
#else
#ifdef __linux__
#define ulink_dbg(...) fprintf(stderr,__VA_ARGS__)
#else
#define ulink_dbg(...)
#endif
#endif
#define CON_ESCAPE_CODE 0x1b
#define CON_SWITCH_BINARY_CODE 'B'
#define CON_SWITCH_TEXT_CODE 'T'
#define CRC_POLY 0x8408
#define LINK_STATE_IDLE 0
#define LINK_STATE_SYNC 1
#define LINK_STATE_PTYPE 2
#define LINK_STATE_LEN0 3
#define LINK_STATE_LEN1 4
#define LINK_STATE_PAYLOAD 5
#define LINK_STATE_CRC0 6
#define LINK_STATE_CRC1 7
#define RX_FSM_TIMEOUT 1000
/* ms */
static
uint16_t
crc_xmodem_update
(
uint16_t
crc
,
uint8_t
data
)
{
int
i
;
crc
=
crc
^
(((
uint16_t
)
data
)
<<
8
);
for
(
i
=
0
;
i
<
8
;
i
++
)
{
if
(
crc
&
0x8000
)
{
crc
=
(
crc
<<
1
)
^
0x1021
;
}
else
{
crc
<<=
1
;
}
}
return
crc
;
}
#ifdef CONFIG_TARGET_ERTM14
static
uint32_t
wrpc_get_ms_tics
(
struct
uart_link
*
link
)
{
return
timer_get_tics
();
}
static
int
wrpc_console_uart_send_byte
(
struct
uart_link
*
link
,
uint8_t
b
)
{
return
console_binary_send_byte
(
&
console_uart_dev
,
b
);
}
static
int
wrpc_console_uart_recv_byte
(
struct
uart_link
*
link
)
{
return
console_binary_recv_byte
(
&
console_uart_dev
)
;
}
int
uart_link_create_wrpc_console
(
struct
uart_link
*
link
)
{
link
->
priv
=
NULL
;
link
->
send_byte
=
wrpc_console_uart_send_byte
;
link
->
recv_byte
=
wrpc_console_uart_recv_byte
;
link
->
get_ms_tics
=
wrpc_get_ms_tics
;
link
->
state
=
LINK_STATE_IDLE
;
link
->
rx_last_tics
=
0
;
return
0
;
};
static
int
wrpc_suart_send_byte
(
struct
uart_link
*
link
,
uint8_t
b
)
{
struct
simple_uart_device
*
suart
=
(
struct
simple_uart_device
*
)
link
->
priv
;
}
static
int
wrpc_suart_recv_byte
(
struct
uart_link
*
link
)
{
struct
simple_uart_device
*
suart
=
(
struct
simple_uart_device
*
)
link
->
priv
;
}
int
uart_link_create_wrpc_suart
(
struct
uart_link
*
link
,
struct
simple_uart_device
*
uart_dev
)
{
link
->
priv
=
uart_dev
;
link
->
send_byte
=
wrpc_suart_send_byte
;
link
->
recv_byte
=
wrpc_suart_recv_byte
;
link
->
get_ms_tics
=
wrpc_get_ms_tics
;
link
->
state
=
LINK_STATE_IDLE
;
link
->
rx_last_tics
=
0
;
return
0
;
};
#endif
#ifdef __linux__
struct
uart_link_priv
{
int
fd
;
int
esc_pending
;
};
int
uart_link_send_byte_raw
(
struct
uart_link
*
link
,
uint8_t
b
)
{
struct
uart_link_priv
*
priv
=
(
struct
uart_link_priv
*
)
link
->
priv
;
int
rv
=
write
(
priv
->
fd
,
&
b
,
1
);
ulink_dbg
(
"TxRaw %x r %d
\n
"
,
b
,
rv
);
return
rv
==
1
?
0
:
-
EBUSY
;
}
int
uart_link_send_byte
(
struct
uart_link
*
link
,
uint8_t
b
)
{
if
(
b
==
CON_ESCAPE_CODE
)
{
if
(
uart_link_send_byte_raw
(
link
,
CON_ESCAPE_CODE
)
<
0
)
return
-
1
;
}
return
uart_link_send_byte_raw
(
link
,
b
);
}
int
uart_link_recv_byte_raw
(
struct
uart_link
*
link
)
{
struct
uart_link_priv
*
priv
=
(
struct
uart_link_priv
*
)
link
->
priv
;
uint8_t
b
;
int
rv
=
read
(
priv
->
fd
,
&
b
,
1
);
return
rv
==
1
?
b
:
-
1
;
}
int
uart_link_recv_byte
(
struct
uart_link
*
link
)
{
return
uart_link_recv_byte_raw
(
link
);
}
int
uart_link_set_binary
(
struct
uart_link
*
link
)
{
struct
uart_link_priv
*
priv
=
(
struct
uart_link_priv
*
)
link
->
priv
;
int
retries
;
for
(
retries
=
0
;
retries
<
3
;
retries
++
)
{
if
(
uart_link_send_byte_raw
(
link
,
CON_ESCAPE_CODE
)
<
0
)
return
-
1
;
if
(
uart_link_send_byte_raw
(
link
,
CON_SWITCH_BINARY_CODE
)
<
0
)
return
-
1
;
}
return
0
;
}
uint32_t
uart_link_get_ms_tics
(
struct
uart_link
*
link
)
{
struct
timezone
tz
=
{
0
,
0
};
struct
timeval
tv
;
gettimeofday
(
&
tv
,
&
tz
);
uint64_t
tics
=
(
uint64_t
)
tv
.
tv_sec
*
1000ULL
+
tv
.
tv_usec
/
1000
;
return
(
uint32_t
)
tics
;
}
int
uart_link_create_linux
(
struct
uart_link
*
link
,
const
char
*
dev_name
,
int
speed
)
{
struct
uart_link_priv
*
priv
=
malloc
(
sizeof
(
struct
uart_link_priv
));
struct
termios
t
;
int
fd
;
int
spd
;
if
(
!
priv
)
return
-
ENOMEM
;
switch
(
speed
)
{
case
921600
:
spd
=
B921600
;
break
;
case
230400
:
spd
=
B230400
;
break
;
case
460800
:
spd
=
B460800
;
break
;
case
115200
:
spd
=
B115200
;
break
;
case
57600
:
spd
=
B57600
;
break
;
case
38400
:
spd
=
B38400
;
break
;
case
19200
:
spd
=
B19200
;
break
;
case
9600
:
spd
=
B9600
;
break
;
default:
return
-
EINVAL
;
}
fd
=
open
(
dev_name
,
O_RDWR
|
O_NONBLOCK
|
O_SYNC
);
if
(
fd
<
0
)
return
fd
;
tcgetattr
(
fd
,
&
t
);
t
.
c_iflag
=
IGNBRK
|
IGNPAR
;
t
.
c_oflag
=
t
.
c_lflag
=
t
.
c_line
=
0
;
t
.
c_cflag
=
CSTOPB
|
CS8
|
CREAD
|
CLOCAL
|
HUPCL
|
spd
;
tcsetattr
(
fd
,
TCSAFLUSH
,
&
t
);
priv
->
fd
=
fd
;
link
->
send_byte
=
uart_link_send_byte
;
link
->
recv_byte
=
uart_link_recv_byte
;
link
->
get_ms_tics
=
uart_link_get_ms_tics
;
link
->
state
=
LINK_STATE_IDLE
;
link
->
priv
=
priv
;
link
->
rx_last_tics
=
0
;
return
uart_link_set_binary
(
link
);
};
int
uart_link_close_linux
(
struct
uart_link
*
link
)
{
struct
uart_link_priv
*
priv
=
(
struct
uart_link_priv
*
)
link
->
priv
;
close
(
priv
->
fd
);
return
0
;
}
#endif
static
uint16_t
crc16
(
unsigned
char
*
buf
,
int
len
)
{
int
i
;
uint16_t
cksum
;
cksum
=
0
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
cksum
=
crc_xmodem_update
(
cksum
,
buf
[
i
]);
}
return
cksum
;
}
int
uart_link_reset
(
struct
uart_link
*
link
)
{
link
->
state
=
LINK_STATE_IDLE
;
link
->
rx_last_tics
=
0
;
}
int
uart_link_send
(
struct
uart_link
*
link
,
struct
uart_packet
*
pkt
)
{
uint8_t
buf
[
ERTM14_MAX_UART_LINK_PAYLOAD
+
16
];
uint16_t
crc
=
0
,
i
;
buf
[
0
]
=
0x55
;
buf
[
1
]
=
0xaa
;
buf
[
2
]
=
pkt
->
ptype
;
buf
[
3
]
=
(
pkt
->
length
>>
8
)
&
0xff
;
buf
[
4
]
=
(
pkt
->
length
&
0xff
);
if
(
pkt
->
length
>
0
)
memcpy
(
buf
+
5
,
pkt
->
payload
,
pkt
->
length
);
crc
=
crc16
(
buf
,
pkt
->
length
+
5
);
buf
[
pkt
->
length
+
5
]
=
(
crc
>>
8
);
buf
[
pkt
->
length
+
6
]
=
(
crc
&
0xff
);
for
(
i
=
0
;
i
<
pkt
->
length
+
7
;
i
++
)
{
int
res
=
link
->
send_byte
(
link
,
buf
[
i
]
);
if
(
res
<
0
)
return
res
;
}
return
0
;
}
#define RX_FSM_PACKET_ERROR -2
#define RX_FSM_NO_DATA -1
#define RX_FSM_NEED_DATA 0
#define RX_FSM_GOT_PACKET 1
static
int
recv_fsm
(
struct
uart_link
*
link
,
struct
uart_packet
**
pkt
)
{
int
rx_byte
=
link
->
recv_byte
(
link
);
uint32_t
current_tics
=
link
->
get_ms_tics
(
link
);
if
(
current_tics
-
link
->
rx_last_tics
>
RX_FSM_TIMEOUT
)
if
(
rx_byte
<
0
)
return
RX_FSM_NO_DATA
;
ulink_dbg
(
"Rx %x state %d
\n
"
,
rx_byte
,
link
->
state
);
switch
(
link
->
state
)
{
case
LINK_STATE_IDLE
:
if
(
rx_byte
==
0x55
)
{
link
->
state
=
LINK_STATE_SYNC
;
link
->
check_crc
=
crc_xmodem_update
(
0
,
0x55
);
}
break
;
case
LINK_STATE_SYNC
:
if
(
rx_byte
==
0xaa
)
{
link
->
state
=
LINK_STATE_PTYPE
;
link
->
check_crc
=
crc_xmodem_update
(
link
->
check_crc
,
0xaa
);
}
else
if
(
rx_byte
==
0x55
)
link
->
state
=
LINK_STATE_SYNC
;
else
link
->
state
=
LINK_STATE_IDLE
;
break
;
case
LINK_STATE_PTYPE
:
link
->
rx_packet
.
ptype
=
rx_byte
;
link
->
check_crc
=
crc_xmodem_update
(
link
->
check_crc
,
rx_byte
);
link
->
state
=
LINK_STATE_LEN0
;
break
;
case
LINK_STATE_LEN0
:
link
->
rx_packet
.
length
=
(
rx_byte
<<
8
);
link
->
check_crc
=
crc_xmodem_update
(
link
->
check_crc
,
rx_byte
);
link
->
state
=
LINK_STATE_LEN1
;
break
;
case
LINK_STATE_LEN1
:
link
->
rx_packet
.
length
|=
rx_byte
;
link
->
check_crc
=
crc_xmodem_update
(
link
->
check_crc
,
rx_byte
);
link
->
rx_count
=
0
;
if
(
link
->
rx_packet
.
length
==
0
)
link
->
state
=
LINK_STATE_CRC0
;
else
link
->
state
=
LINK_STATE_PAYLOAD
;
break
;
case
LINK_STATE_PAYLOAD
:
if
(
link
->
rx_count
==
link
->
rx_packet
.
length
-
1
)
{
link
->
state
=
LINK_STATE_CRC0
;
}
link
->
check_crc
=
crc_xmodem_update
(
link
->
check_crc
,
rx_byte
);
if
(
link
->
rx_count
<
ERTM14_MAX_UART_LINK_PAYLOAD
)
link
->
rx_packet
.
payload
[
link
->
rx_count
++
]
=
rx_byte
;
break
;
case
LINK_STATE_CRC0
:
link
->
rx_crc
=
(
rx_byte
<<
8
);
link
->
state
=
LINK_STATE_CRC1
;
break
;
case
LINK_STATE_CRC1
:
{
link
->
rx_crc
|=
rx_byte
;
link
->
state
=
LINK_STATE_IDLE
;
if
(
link
->
rx_count
!=
link
->
rx_packet
.
length
)
{
// blink(1);
return
RX_FSM_PACKET_ERROR
;
}
else
if
(
link
->
rx_crc
!=
link
->
check_crc
)
{
//blink(2);
return
RX_FSM_PACKET_ERROR
;
}
else
{
//blink(0);
*
pkt
=
&
link
->
rx_packet
;
return
RX_FSM_GOT_PACKET
;
}
}
}
return
RX_FSM_NEED_DATA
;
}
int
uart_link_recv
(
struct
uart_link
*
link
,
struct
uart_packet
**
pkt
,
int
timeout_ms
)
{
uint32_t
start_tics
=
link
->
get_ms_tics
(
link
);
for
(;;)
{
int
ret
=
recv_fsm
(
link
,
pkt
);
if
(
timeout_ms
==
0
)
return
ret
;
else
if
(
ret
==
RX_FSM_PACKET_ERROR
||
ret
==
RX_FSM_GOT_PACKET
)
return
ret
;
else
{
// check timeout
if
(
link
->
get_ms_tics
(
link
)
-
start_tics
>=
timeout_ms
)
{
ulink_dbg
(
"Rx timeout expired
\n
"
);
uart_link_reset
(
link
);
return
-
ECANCELED
;
}
else
{
#ifdef __linux__
usleep
(
1000
);
#endif
}
}
}
return
0
;
}
#ifdef __linux__
#define ERTM14_UART_PTYPE_PING 1
#define ERTM14_UART_PTYPE_SNMP_REQ 2
#define ERTM14_UART_PTYPE_SNMP_RESP 3
#define ERTM14_UART_PTYPE_MMC_STATUS_REQ 4
int
main
()
{
struct
uart_link
link
;
int
rv
=
uart_link_create_linux
(
&
link
,
"/dev/ttyUSB2"
,
921600
);
for
(;;)
{
fprintf
(
stderr
,
"Ping!
\n
"
);
struct
uart_packet
pkt
;
pkt
.
ptype
=
ERTM14_UART_PTYPE_PING
;
pkt
.
length
=
0
;
uart_link_send
(
&
link
,
&
pkt
);
struct
uart_packet
*
rx_pkt
;
int
retries
=
0
;
int
stat
=
uart_link_recv
(
&
link
,
&
rx_pkt
,
1000
);
if
(
stat
>
0
)
{
fprintf
(
stderr
,
"Pong [%d]
\n
"
,
rx_pkt
->
length
);
}
}
return
0
;
}
void
blink
(
int
id
)
{
}
#endif
\ No newline at end of file
lib/ertm14-uart-link.h
0 → 100644
View file @
0d6df9e0
#ifndef __ERTM14_UART_LINK_H
#define __ERTM14_UART_LINK_H
#include <stdint.h>
#define ERTM14_MAX_UART_LINK_PAYLOAD 512
struct
simple_uart_device
;
struct
uart_packet
{
uint8_t
ptype
;
uint16_t
length
;
uint8_t
payload
[
ERTM14_MAX_UART_LINK_PAYLOAD
];
};
struct
uart_link
{
int
(
*
send_byte
)(
struct
uart_link
*
link
,
uint8_t
byte
);
int
(
*
recv_byte
)(
struct
uart_link
*
link
);
uint32_t
(
*
get_ms_tics
)(
struct
uart_link
*
link
);
void
*
priv
;
int
state
;
int
rx_count
;
uint16_t
rx_crc
,
check_crc
;
uint32_t
rx_last_tics
;
struct
uart_packet
rx_packet
;
};
#ifdef __linux__
int
uart_link_create_linux
(
struct
uart_link
*
link
,
const
char
*
dev_name
,
int
speed
);
int
uart_link_close_linux
(
struct
uart_link
*
link
);
#endif
#ifdef CONFIG_TARGET_ERTM14
int
uart_link_create_wrpc_console
(
struct
uart_link
*
link
);
int
uart_link_create_wrpc_suart
(
struct
uart_link
*
link
,
struct
simple_uart_device
*
uart_dev
);
#endif
#ifdef MODULE_ERTM14_FPGA_UART // openMMC
#endif
int
uart_link_reset
(
struct
uart_link
*
link
);
int
uart_link_send
(
struct
uart_link
*
link
,
struct
uart_packet
*
pkt
);
int
uart_link_recv
(
struct
uart_link
*
link
,
struct
uart_packet
**
pkt
,
int
timeout_ms
);
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment