Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
portal-core
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
portal
portal-core
Commits
66f28133
Commit
66f28133
authored
13 years ago
by
da1l6
Browse files
Options
Downloads
Patches
Plain Diff
common/transport: Make receive interrupt driven to allow receive while the main loop is busy.
parent
4631e16a
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
common/transport/transport.c
+97
-176
97 additions, 176 deletions
common/transport/transport.c
common/transport/transport.h
+0
-3
0 additions, 3 deletions
common/transport/transport.h
with
97 additions
and
179 deletions
common/transport/transport.c
+
97
−
176
View file @
66f28133
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
#define USART_NAME USART
#define USART_NAME USART
#undef USART_USE_AS_STDOUT
#undef USART_USE_AS_STDOUT
#define BAUD
24
00
#define BAUD
96
00
// #define USART_USE_AS_STDOUT //Debugging only!
// #define USART_USE_AS_STDOUT //Debugging only!
void
USART_recv_interrupt
(
void
);
void
USART_recv_interrupt
(
void
);
#define USART_NUMBER TRANSPORT_USART_NUMBER
#define USART_NUMBER TRANSPORT_USART_NUMBER
...
@@ -26,18 +26,82 @@ void USART_recv_interrupt(void);
...
@@ -26,18 +26,82 @@ void USART_recv_interrupt(void);
interrupt_msg_handler_t
interrupt_msg_table
[
16
]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
interrupt_msg_handler_t
interrupt_msg_table
[
16
]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
volatile
uint8_t
msg_start_received
=
0
;
#define RECV_IDLE 0x00
#define RECV_START 0x01
uint16_t
transport_receive_char
(
uint16_t
timeout
);
#define RECV_BODY 0x02
#define RECV_CHECKSUM 0x03
#define RECV_FINISHED 0x04
#define RECV_ERROR 0x0A
#define RECV_ESCAPE_FLAG 0x40
#define RECV_INTERRUPT_FLAG 0x80
#define RECV_SET_STATE(s) {msg_recv_state = (msg_recv_state & (RECV_ESCAPE_FLAG | RECV_INTERRUPT_FLAG)) | s;}
#define RECV_STATE() (msg_recv_state & ~(RECV_ESCAPE_FLAG | RECV_INTERRUPT_FLAG))
volatile
uint8_t
msg_recv_state
=
RECV_IDLE
;
volatile
uint8_t
msg_recv_pos
=
0
;
volatile
uint8_t
msg_recv_body_length
=
0
;
volatile
uint16_t
msg_recv_checksum
=
0
;
#define RECV_MAX_LENGTH 255
volatile
uint8_t
msg_recv_buffer
[
RECV_MAX_LENGTH
];
uint8_t
transport_unescape
(
uint8_t
c
);
void
USART_recv_interrupt
(
void
){
void
USART_recv_interrupt
(
void
){
uint16_t
ret
=
transport_receive_char
(
400
);
uint8_t
c
=
USART_read_char
();
// printf("RXI %04x\n", ret);
if
(
msg_recv_state
&
RECV_INTERRUPT_FLAG
){
// lcd_write_char('R');
if
(
c
!=
INTERRUPT_NONE
&&
interrupt_msg_table
[
INTERRUPT_NUM
(
c
)]){
if
(
ret
==
RET_MSG_START
){
interrupt_msg_table
[
INTERRUPT_NUM
(
c
)]();
msg_start_received
=
1
;
}
// printf("Start\n");
msg_recv_state
&=
~
RECV_INTERRUPT_FLAG
;
USART_disable_rx_interrupt
();
}
else
if
(
c
==
SC_ESCAPE
){
msg_recv_state
|=
RECV_ESCAPE_FLAG
;
}
else
if
(
c
==
SC_INTERRUPT
){
msg_recv_state
|=
RECV_INTERRUPT_FLAG
;
}
else
if
(
c
==
SC_MSG_START
){
RECV_SET_STATE
(
RECV_START
);
msg_recv_pos
=
0
;
}
else
if
(
c
==
SC_MSG_END
){
msg_recv_body_length
=
msg_recv_pos
;
RECV_SET_STATE
(
RECV_CHECKSUM
);
msg_recv_pos
=
0
;
}
else
{
if
(
msg_recv_state
&
RECV_ESCAPE_FLAG
){
c
=
transport_unescape
(
c
);
msg_recv_state
&=
~
RECV_ESCAPE_FLAG
;
}
if
(
RECV_STATE
()
==
RECV_START
){
msg_recv_pos
=
0
;
RECV_SET_STATE
(
RECV_BODY
);
}
if
(
RECV_STATE
()
==
RECV_BODY
){
if
(
msg_recv_pos
<
RECV_MAX_LENGTH
){
msg_recv_buffer
[
msg_recv_pos
]
=
c
;
msg_recv_pos
++
;
}
}
else
if
(
RECV_STATE
()
==
RECV_CHECKSUM
){
if
(
msg_recv_pos
==
0
)
msg_recv_checksum
=
c
;
if
(
msg_recv_pos
==
1
)
{
msg_recv_checksum
|=
c
<<
8
;
RECV_SET_STATE
(
RECV_FINISHED
);
}
msg_recv_pos
++
;
}
}
}
uint8_t
transport_unescape
(
uint8_t
c
){
if
(
c
==
EC_2B
){
return
0x2B
;
}
else
if
(
c
==
EC_D4
){
return
0xD4
;
}
else
if
(
c
==
EC_5C
){
return
0x5C
;
}
else
if
(
c
==
EC_AA
){
return
0xAA
;
}
else
{
return
c
;
}
}
}
}
...
@@ -89,12 +153,15 @@ void transport_send_message(uint8_t* body, uint8_t length){
...
@@ -89,12 +153,15 @@ void transport_send_message(uint8_t* body, uint8_t length){
for
(
uint8_t
i
=
0
;
i
<
length
;
i
++
){
for
(
uint8_t
i
=
0
;
i
<
length
;
i
++
){
transport_send_char
(
body
[
i
]);
transport_send_char
(
body
[
i
]);
// printf(">%02x>", body[i]);
checksum
=
_crc16_update
(
checksum
,
body
[
i
]);
checksum
=
_crc16_update
(
checksum
,
body
[
i
]);
}
}
USART_transmit_char
(
SC_MSG_END
);
USART_transmit_char
(
SC_MSG_END
);
transport_send_char
(
checksum
&
0xFF
);
transport_send_char
(
checksum
&
0xFF
);
transport_send_char
(
checksum
>>
8
);
transport_send_char
(
checksum
>>
8
);
USART_flush
();
}
}
void
transport_send_interrupt_message
(
uint8_t
interrupt
){
void
transport_send_interrupt_message
(
uint8_t
interrupt
){
...
@@ -107,177 +174,31 @@ void transport_send_interrupt_message(uint8_t interrupt){
...
@@ -107,177 +174,31 @@ void transport_send_interrupt_message(uint8_t interrupt){
}
}
uint8_t
transport_data_available
(
void
){
uint8_t
transport_data_available
(
void
){
return
msg_start_received
;
return
msg_recv_state
==
RECV_FINISHED
;
}
uint16_t
transport_handle_interrupt_msg
(
uint16_t
timeout
){
uint8_t
num_interrupts
=
1
;
uint16_t
ret
=
SC_INTERRUPT
;
// while (ret == SC_INTERRUPT){
// ret = USART_read_char_timeout(timeout);
// if (ret == ERR_TIMEOUT) return ERR_TIMEOUT;
// if (ret == SC_INTERRUPT){
// if (num_interrupts < 255){
// num_interrupts++;
// } else { //more than 255 nested interrupt msgs?! somebody is fucking with us.
// return TRANSPORT_ERR_NESTED_INTERRUPTS;
// }
// }
// }
//
// printf("Int");
for
(
uint8_t
i
=
0
;
i
<
num_interrupts
;
i
++
){
ret
=
USART_read_char_timeout
(
timeout
);
if
(
ret
==
ERR_TIMEOUT
)
return
ERR_TIMEOUT
;
if
(
ret
!=
INTERRUPT_NONE
&&
interrupt_msg_table
[
INTERRUPT_NUM
(
ret
)]){
interrupt_msg_table
[
INTERRUPT_NUM
(
ret
)]();
}
}
return
0
;
}
}
uint16_t
transport_receive_char
(
uint16_t
timeout
){
uint16_t
transport_receive_message
(
uint8_t
*
buffer
,
uint8_t
length
,
uint16_t
timeout
){
uint16_t
ret
;
uint8_t
c
;
while
(
1
){
while
(
RECV_STATE
()
!=
RECV_FINISHED
&&
timeout
>
0
){
ret
=
USART_read_char_timeout
(
timeout
);
timeout
--
;
if
(
ret
==
ERR_TIMEOUT
)
return
TRANSPORT_ERR_TIMEOUT
;
_delay_us
(
100
);
c
=
ret
&
0xFF
;
if
(
c
==
SC_ESCAPE
){
while
(
1
){
ret
=
USART_read_char_timeout
(
timeout
);
if
(
ret
==
ERR_TIMEOUT
)
return
TRANSPORT_ERR_TIMEOUT
;
c
=
ret
&
0xFF
;
if
(
c
==
SC_INTERRUPT
)
{
ret
=
transport_handle_interrupt_msg
(
timeout
);
if
(
ret
==
ERR_TIMEOUT
)
return
TRANSPORT_ERR_TIMEOUT
;
if
(
ret
==
TRANSPORT_ERR_NESTED_INTERRUPTS
)
return
TRANSPORT_ERR_NESTED_INTERRUPTS
;
//loop again, to read the next char (the one that was about to be escaped, when this interrupt came in)
}
else
{
break
;
}
}
if
(
c
==
EC_2B
){
return
0x2B
;
}
else
if
(
c
==
EC_D4
){
return
0xD4
;
}
else
if
(
c
==
EC_5C
){
return
0x5C
;
}
else
if
(
c
==
EC_AA
){
return
0xAA
;
}
else
{
//keep unknown escape char unchanged //TODO: Handle this properly? Error?
return
c
;
}
}
else
if
(
c
==
SC_MSG_END
){
return
RET_MSG_END
;
}
else
if
(
c
==
SC_MSG_START
){
return
RET_MSG_START
;
}
else
if
(
c
==
SC_INTERRUPT
){
ret
=
transport_handle_interrupt_msg
(
timeout
);
if
(
ret
==
ERR_TIMEOUT
)
return
TRANSPORT_ERR_TIMEOUT
;
if
(
ret
==
TRANSPORT_ERR_NESTED_INTERRUPTS
)
return
TRANSPORT_ERR_NESTED_INTERRUPTS
;
//we have nothing to return, so loop again to read the next char.
}
else
{
//literal char
return
c
;
}
}
}
}
uint16_t
_transport_receive_message
(
uint8_t
*
buffer
,
uint8_t
length
,
uint16_t
timeout
){
uint16_t
ret
=
0
;
uint8_t
c
=
0
;
uint8_t
recv_length
=
0
;
uint16_t
real_checksum
=
0xFFFF
;
uint16_t
expected_checksum
;
uint8_t
has_body
=
1
;
//Wait for message start char (if the interrupt didn't pick it up for us already)
if
(
RECV_STATE
()
!=
RECV_FINISHED
){
if
(
!
msg_start_received
){
return
TRANSPORT_ERR_TIMEOUT
;
while
(
1
){
}
else
if
(
msg_recv_body_length
>
length
)
{
ret
=
transport_receive_char
(
timeout
);
RECV_SET_STATE
(
RECV_IDLE
);
if
(
ret
==
TRANSPORT_ERR_TIMEOUT
)
return
TRANSPORT_ERR_TIMEOUT
;
return
TRANSPORT_ERR_MESSAGE_TOO_LONG
;
if
(
ret
==
RET_MSG_START
)
break
;
}
}
else
{
}
else
{
msg_start_received
=
0
;
uint16_t
checksum
=
0xFFFF
;
}
for
(
uint8_t
i
=
0
;
i
<
msg_recv_body_length
;
i
++
){
checksum
=
_crc16_update
(
checksum
,
msg_recv_buffer
[
i
]);
//The start char can be repeated multiple times, wait for something else
buffer
[
i
]
=
msg_recv_buffer
[
i
];
while
(
1
){
ret
=
transport_receive_char
(
timeout
);
if
(
ret
==
TRANSPORT_ERR_TIMEOUT
)
return
TRANSPORT_ERR_TIMEOUT
;
if
(
ret
==
TRANSPORT_ERR_NESTED_INTERRUPTS
)
return
TRANSPORT_ERR_NESTED_INTERRUPTS
;
if
(
ret
==
RET_MSG_END
)
{
has_body
=
0
;
break
;};
//end after start -> empty message
if
(
ret
!=
RET_MSG_START
)
break
;
}
if
(
has_body
){
c
=
ret
&
0xFF
;
//Receive the message body
while
(
1
){
if
(
recv_length
<
length
){
//write byte to the buffer (if not full)
buffer
[
recv_length
]
=
c
;
recv_length
++
;
}
else
{
return
TRANSPORT_ERR_MESSAGE_TOO_LONG
;
}
real_checksum
=
_crc16_update
(
real_checksum
,
c
);
//checksum byte
//Receive next char
ret
=
transport_receive_char
(
timeout
);
if
(
ret
==
TRANSPORT_ERR_TIMEOUT
)
return
TRANSPORT_ERR_TIMEOUT
;
if
(
ret
==
TRANSPORT_ERR_NESTED_INTERRUPTS
)
return
TRANSPORT_ERR_NESTED_INTERRUPTS
;
if
(
ret
==
RET_MSG_START
)
return
TRANSPORT_ERR_MESSAGE_ABORT
;
//no start char expected, this is an error (truncated message?)
if
(
ret
==
RET_MSG_END
)
break
;
//end char (literal) received
c
=
ret
&
0xFF
;
}
}
RECV_SET_STATE
(
RECV_IDLE
);
if
(
checksum
!=
msg_recv_checksum
)
return
TRANSPORT_ERR_CHECKSUM_FAIL
;
return
msg_recv_body_length
;
}
}
//checksum (low byte)
ret
=
transport_receive_char
(
timeout
);
if
(
ret
==
TRANSPORT_ERR_TIMEOUT
)
return
TRANSPORT_ERR_TIMEOUT
;
if
(
ret
==
TRANSPORT_ERR_NESTED_INTERRUPTS
)
return
TRANSPORT_ERR_NESTED_INTERRUPTS
;
if
(
ret
==
RET_MSG_START
)
return
TRANSPORT_ERR_MESSAGE_ABORT
;
//no start char expected, this is an error (truncated message?)
if
(
ret
==
RET_MSG_END
)
return
TRANSPORT_ERR_UNEXPCETED_END
;
//doesnt belong here, don't know how to handle that
expected_checksum
=
ret
&
0xFF
;
//checksum (high byte)
ret
=
transport_receive_char
(
timeout
);
if
(
ret
==
TRANSPORT_ERR_TIMEOUT
)
return
TRANSPORT_ERR_TIMEOUT
;
if
(
ret
==
TRANSPORT_ERR_NESTED_INTERRUPTS
)
return
TRANSPORT_ERR_NESTED_INTERRUPTS
;
if
(
ret
==
RET_MSG_START
)
return
TRANSPORT_ERR_MESSAGE_ABORT
;
//no start char expected, this is an error (truncated message?)
if
(
ret
==
RET_MSG_END
)
return
TRANSPORT_ERR_UNEXPCETED_END
;
//doesnt belong here, don't know how to handle that
expected_checksum
|=
(
ret
&
0xFF
)
<<
8
;
if
(
expected_checksum
!=
real_checksum
){
// lcd_clear();
// lcd_home();
// for (uint8_t i = 0; i < recv_length; i++){
// lcd_write_byte_hex(buffer[i]);
// }
// _delay_ms(10000);
return
TRANSPORT_ERR_CHECKSUM_FAIL
;
}
return
recv_length
;
}
}
uint16_t
transport_receive_message
(
uint8_t
*
buffer
,
uint8_t
length
,
uint16_t
timeout
){
USART_disable_rx_interrupt
();
//Disable RX interrupt, we are going to poll rx from here now.
uint16_t
ret
=
_transport_receive_message
(
buffer
,
length
,
timeout
);
USART_enable_rx_interrupt
();
//Enable RX interrupt again.
return
ret
;
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
common/transport/transport.h
+
0
−
3
View file @
66f28133
...
@@ -8,10 +8,7 @@
...
@@ -8,10 +8,7 @@
#define TRANSPORT_ERR_TIMEOUT 0xFFFF
#define TRANSPORT_ERR_TIMEOUT 0xFFFF
#define TRANSPORT_ERR_CHECKSUM_FAIL 0xFFEE
#define TRANSPORT_ERR_CHECKSUM_FAIL 0xFFEE
#define TRANSPORT_ERR_MESSAGE_ABORT 0xFFDD
#define TRANSPORT_ERR_MESSAGE_TOO_LONG 0xFFCC
#define TRANSPORT_ERR_MESSAGE_TOO_LONG 0xFFCC
#define TRANSPORT_ERR_UNEXPCETED_END 0xFFBB
#define TRANSPORT_ERR_NESTED_INTERRUPTS 0xFFAA
#define TRANSPORT_IS_ERROR(ret) (((ret) & 0xFF00) != 0)
#define TRANSPORT_IS_ERROR(ret) (((ret) & 0xFF00) != 0)
typedef
void
(
*
interrupt_msg_handler_t
)(
void
);
typedef
void
(
*
interrupt_msg_handler_t
)(
void
);
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment