251 lines
6.0 KiB
C
251 lines
6.0 KiB
C
/**
|
|
* servicelink_v2.c Servicelink Version 2 Implementierung
|
|
*
|
|
**/
|
|
|
|
#include <hwo/chksum.h>
|
|
#include <hwo/bits.h>
|
|
|
|
#include <rb2/regbus.h>
|
|
|
|
#include <sys/errno.h>
|
|
#include <sys/assert.h>
|
|
|
|
#include <usb/usb.h>
|
|
|
|
#include <usb/servicelink.h>
|
|
|
|
/**
|
|
|
|
servicelink nutzt CDC-ACM Profil
|
|
Endpunkt 3 für RX (HOST->DEV)
|
|
Endpunkt 4 für TX (DEV->HOST)
|
|
|
|
**/
|
|
|
|
/* __SL2_ASYNC defines asynchronous servicelink worker */
|
|
#define __SL2_ASYNC__
|
|
|
|
#define SL2_POOL_SIZE 24
|
|
|
|
#define EP_RX 4
|
|
#define EP_TX 3
|
|
|
|
#define SL2_TIMEOUT 25000L
|
|
|
|
|
|
|
|
static sl_v2_telegram_list_t
|
|
*current_rx,
|
|
*current_tx;
|
|
|
|
static LIST(queue_pool); // sl_telegram_list_t Unbenutzt
|
|
static LIST(queue_tx); // sl_telegram_list_t Wartet auf Senden...
|
|
static LIST(queue_pending); // sl_telegram_list_t Wartet auf RegBUS Antwort...
|
|
|
|
int sl2_dbg_free_telegrams(void){
|
|
return list_count( &queue_pool );
|
|
};
|
|
|
|
|
|
int sl2_2_rb2(sl_v2_telegram_list_t *tele){
|
|
|
|
#ifdef __SL2_ASYNC__
|
|
uint8_t type;
|
|
|
|
//usb_device.state.Debugged = usb_device.state.Debugged ? 0 : 1;
|
|
|
|
|
|
type = (tele->sl_telegram.is_float ? RDT_FLOAT : RDT_INT32) |
|
|
(tele->sl_telegram.has_value ? RDT_WRITE : 0);
|
|
|
|
if (rb2_build_request( &(tele->rb2_request), (RB2_ADDR){ ax: tele->sl_telegram.ax, node:tele->sl_telegram.node}, tele->sl_telegram.register_no, type, &tele->sl_telegram.value.i32) < 0){
|
|
tele->sl_telegram.failed = 1;
|
|
list_append( &(tele->list), &queue_tx );
|
|
} else {
|
|
|
|
if (rb2_enqueue_pending( &(tele->rb2_request) ) < 0){
|
|
tele->sl_telegram.failed = 1;
|
|
list_append( &(tele->list), &queue_tx );
|
|
} else {
|
|
rb2_route( &(tele->rb2_request.telegram) );
|
|
|
|
tele->timeout = systick_ticks() + SL2_TIMEOUT;
|
|
list_append( &(tele->list), &queue_pending );
|
|
};
|
|
};
|
|
|
|
|
|
#else
|
|
if (tele->sl_telegram.is_float){
|
|
if (tele->sl_telegram.has_value){
|
|
if (rb2_write_float( (RB2_ADDR){ ax: tele->sl_telegram.ax, node:tele->sl_telegram.node}, tele->sl_telegram.register_no, &tele->sl_telegram.value.f32 ) < 0){
|
|
tele->sl_telegram.failed = 1;
|
|
} else {
|
|
tele->sl_telegram.has_value = 0;
|
|
};
|
|
} else {
|
|
if (rb2_read_float( (RB2_ADDR){ ax: tele->sl_telegram.ax, node:tele->sl_telegram.node}, tele->sl_telegram.register_no, &tele->sl_telegram.value.f32 ) < 0){
|
|
tele->sl_telegram.failed = 1;
|
|
} else {
|
|
tele->sl_telegram.has_value = 1;
|
|
};
|
|
};
|
|
|
|
} else {
|
|
if (tele->sl_telegram.has_value){
|
|
if (rb2_write_int32( (RB2_ADDR){ ax: tele->sl_telegram.ax, node:tele->sl_telegram.node}, tele->sl_telegram.register_no, &tele->sl_telegram.value.i32 ) < 0){
|
|
tele->sl_telegram.failed = 1;
|
|
} else {
|
|
tele->sl_telegram.has_value = 0;
|
|
};
|
|
} else {
|
|
if (rb2_read_int32( (RB2_ADDR){ ax: tele->sl_telegram.ax, node:tele->sl_telegram.node}, tele->sl_telegram.register_no, &tele->sl_telegram.value.i32 ) < 0){
|
|
tele->sl_telegram.failed = 1;
|
|
} else {
|
|
tele->sl_telegram.has_value = 1;
|
|
};
|
|
};
|
|
};
|
|
|
|
list_append( &(tele->list), &queue_tx );
|
|
#endif
|
|
|
|
return ESUCCESS;
|
|
};
|
|
|
|
#ifdef __SL2_ASYNC__
|
|
|
|
void sl2_async_check(void){
|
|
list_t *l,*t;
|
|
sl_v2_telegram_list_t
|
|
*tele;
|
|
|
|
for_each_list_entry_save(l, t, &queue_pending){
|
|
tele = list_entry( l, sl_v2_telegram_list_t, list );
|
|
|
|
if (tele->rb2_request.telegram.flags.fail){
|
|
|
|
rb2_unqueue_pending( &(tele->rb2_request) );
|
|
list_remove( &(tele->list) );
|
|
|
|
tele->sl_telegram.failed = 1;
|
|
tele->sl_telegram.value.i32 = tele->rb2_request.telegram.i32;
|
|
|
|
list_append( &(tele->list), &queue_tx );
|
|
|
|
} else if (tele->rb2_request.telegram.flags.response) {
|
|
|
|
rb2_unqueue_pending( &(tele->rb2_request) );
|
|
list_remove( &(tele->list) );
|
|
|
|
tele->sl_telegram.has_value = !tele->sl_telegram.has_value;
|
|
if (tele->sl_telegram.has_value){
|
|
tele->sl_telegram.value.i32 = tele->rb2_request.telegram.i32;
|
|
};
|
|
|
|
list_append( &(tele->list), &queue_tx );
|
|
|
|
} else if (tele->timeout < systick_ticks()) {
|
|
|
|
rb2_unqueue_pending( &(tele->rb2_request) );
|
|
list_remove( &(tele->list) );
|
|
|
|
tele->sl_telegram.failed = 1;
|
|
tele->sl_telegram.timeout = 1;
|
|
|
|
list_append( &(tele->list), &queue_tx );
|
|
|
|
};
|
|
};
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
void servicelink2(void *_arg) {
|
|
sl_v2_telegram_list_t
|
|
*tele;
|
|
list_t *l;
|
|
|
|
int i;
|
|
|
|
thread_set_priority( NULL, TP_LOW );
|
|
|
|
for (i=0;i < SL2_POOL_SIZE;i++){
|
|
tele = malloc( sizeof( sl_v2_telegram_list_t ) );
|
|
if (tele){
|
|
memset( tele, 0x00, sizeof( sl_v2_telegram_list_t) );
|
|
list_append( &(tele->list), &queue_pool );
|
|
};
|
|
};
|
|
|
|
while (1){
|
|
|
|
while (usb_device_has_configuration(0)){
|
|
|
|
if (current_rx){
|
|
list_remove( &(current_rx->list) );
|
|
list_append( &(current_rx->list), &queue_pool );
|
|
current_rx = NULL;
|
|
};
|
|
if (current_tx){
|
|
list_remove( &(current_tx->list) );
|
|
list_append( &(current_tx->list), &queue_pool );
|
|
current_tx = NULL;
|
|
};
|
|
|
|
wait_ms(100);
|
|
};
|
|
|
|
wait_ms(1);
|
|
|
|
if (usb_endpoint_check_buffer( EP_RX ) <= 0) {
|
|
usb_endpoint_unset_buffer( EP_RX );
|
|
|
|
if (current_rx){
|
|
sl2_2_rb2( current_rx );
|
|
current_rx = NULL;
|
|
};
|
|
if (!current_rx){
|
|
l = list_fetch_first( &queue_pool );
|
|
if (l){
|
|
current_rx = list_entry( l, sl_v2_telegram_list_t, list );
|
|
usb_endpoint_set_buffer( EP_RX, &(current_rx->sl_telegram), sizeof( sl_v2_telegram_t ) );
|
|
current_rx->timeout = systick_ticks() + SL2_TIMEOUT;
|
|
} else {
|
|
};
|
|
};
|
|
} else {
|
|
if (current_rx && (current_rx->timeout < systick_ticks())){ // Reset Endpoint Buffer for resync...
|
|
usb_endpoint_set_buffer( EP_RX, &(current_rx->sl_telegram), sizeof( sl_v2_telegram_t ) );
|
|
current_rx->timeout = systick_ticks() + SL2_TIMEOUT;
|
|
};
|
|
};
|
|
|
|
#ifdef __SL2_ASYNC__
|
|
|
|
sl2_async_check();
|
|
|
|
#endif
|
|
|
|
|
|
if (usb_endpoint_check_buffer( EP_TX ) <= 0) {
|
|
if (current_tx){
|
|
list_append( &(current_tx->list), &queue_pool );
|
|
current_tx = NULL;
|
|
};
|
|
if (!current_tx){
|
|
l = list_fetch_first( &queue_tx );
|
|
if (l){
|
|
current_tx = list_entry( l, sl_v2_telegram_list_t, list );
|
|
usb_endpoint_set_buffer( EP_TX, &(current_tx->sl_telegram), sizeof( sl_v2_telegram_t ) );
|
|
} else {
|
|
usb_endpoint_unset_buffer( EP_TX );
|
|
};
|
|
};
|
|
};
|
|
|
|
};
|
|
};
|