2014-11-25 23:10:29 +08:00
|
|
|
/** \file
|
|
|
|
* \brief Example code for Simple Open EtherCAT master
|
|
|
|
*
|
|
|
|
* This is a minimal example running rt-kernel TTOS. Check
|
2015-11-04 20:02:33 +08:00
|
|
|
* tutorial files in documentations for som steps to get your
|
2014-11-25 23:10:29 +08:00
|
|
|
* system running.
|
|
|
|
* (c)Andreas Karlsson 2012
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <kern.h>
|
2015-12-18 22:56:33 +08:00
|
|
|
#include "ethercat.h"
|
2014-11-25 23:10:29 +08:00
|
|
|
#include "string.h"
|
|
|
|
#include <oshw.h>
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <defBF537.h>
|
|
|
|
|
|
|
|
#define pPORTFIO_SET ((vuint16_t *)PORTFIO_SET)
|
|
|
|
#define pPORTFIO_CLEAR ((vuint16_t *)PORTFIO_CLEAR)
|
|
|
|
#define pPORTFIO_DIR ((vuint16_t *)PORTFIO_DIR)
|
|
|
|
|
|
|
|
#define EK1100_1 1
|
|
|
|
#define EL4001_1 2
|
|
|
|
#define EL3061_1 3
|
|
|
|
#define EL1008_1 4
|
|
|
|
#define EL1008_2 5
|
|
|
|
#define EL2622_1 6
|
|
|
|
#define EL2622_2 7
|
|
|
|
#define EL2622_3 8
|
|
|
|
#define EL2622_4 9
|
|
|
|
#define NUMBER_OF_SLAVES 9
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
uint8 in1;
|
|
|
|
uint8 in2;
|
|
|
|
uint8 in3;
|
|
|
|
uint8 in4;
|
|
|
|
uint8 in5;
|
|
|
|
uint8 in6;
|
|
|
|
uint8 in7;
|
|
|
|
uint8 in8;
|
|
|
|
} in_EL1008_t;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
uint8 out1;
|
|
|
|
uint8 out2;
|
|
|
|
} out_EL2622_t;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int16 out1;
|
|
|
|
} out_EL4001_t;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int32 in1;
|
|
|
|
} in_EL3061_t;
|
|
|
|
|
|
|
|
out_EL4001_t slave_EL4001_1;
|
|
|
|
in_EL3061_t slave_EL3061_1;
|
|
|
|
in_EL1008_t slave_EL1008_1;
|
|
|
|
in_EL1008_t slave_EL1008_2;
|
|
|
|
out_EL2622_t slave_EL2622_1;
|
|
|
|
out_EL2622_t slave_EL2622_2;
|
|
|
|
out_EL2622_t slave_EL2622_3;
|
|
|
|
|
|
|
|
uint32 network_configuration(void)
|
|
|
|
{
|
|
|
|
/* Do we got expected number of slaves from config */
|
|
|
|
if (ec_slavecount < NUMBER_OF_SLAVES)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Verify slave by slave that it is correct*/
|
|
|
|
if (strcmp(ec_slave[EK1100_1].name,"EK1100"))
|
|
|
|
return 0;
|
|
|
|
else if (strcmp(ec_slave[EL4001_1].name,"EL4001"))
|
|
|
|
return 0;
|
|
|
|
else if (strcmp(ec_slave[EL3061_1].name,"EL3061"))
|
|
|
|
return 0;
|
|
|
|
else if (strcmp(ec_slave[EL1008_1].name,"EL1008"))
|
|
|
|
return 0;
|
|
|
|
else if (strcmp(ec_slave[EL1008_2].name,"EL1008"))
|
|
|
|
return 0;
|
|
|
|
else if (strcmp(ec_slave[EL2622_1].name,"EL2622"))
|
|
|
|
return 0;
|
|
|
|
else if (strcmp(ec_slave[EL2622_2].name,"EL2622"))
|
|
|
|
return 0;
|
|
|
|
else if (strcmp(ec_slave[EL2622_3].name,"EL2622"))
|
|
|
|
return 0;
|
|
|
|
else if (strcmp(ec_slave[EL2622_4].name,"EL2622"))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32 get_input_int32(uint16 slave_no,uint8 module_index)
|
|
|
|
{
|
|
|
|
int32 return_value;
|
|
|
|
uint8 *data_ptr;
|
|
|
|
/* Get the IO map pointer from the ec_slave struct */
|
|
|
|
data_ptr = ec_slave[slave_no].inputs;
|
|
|
|
/* Move pointer to correct module index */
|
|
|
|
data_ptr += module_index * 4;
|
|
|
|
/* Read value byte by byte since all targets can't handle misaligned
|
|
|
|
* addresses
|
|
|
|
*/
|
|
|
|
return_value = *data_ptr++;
|
|
|
|
return_value += (*data_ptr++ << 8);
|
|
|
|
return_value += (*data_ptr++ << 16);
|
|
|
|
return_value += (*data_ptr++ << 24);
|
|
|
|
|
|
|
|
return return_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_input_int32 (uint16 slave_no, uint8 module_index, int32 value)
|
|
|
|
{
|
|
|
|
uint8 *data_ptr;
|
|
|
|
/* Get the IO map pointer from the ec_slave struct */
|
|
|
|
data_ptr = ec_slave[slave_no].inputs;
|
|
|
|
/* Move pointer to correct module index */
|
|
|
|
data_ptr += module_index * 4;
|
|
|
|
/* Read value byte by byte since all targets can handle misaligned
|
|
|
|
* addresses
|
|
|
|
*/
|
|
|
|
*data_ptr++ = (value >> 0) & 0xFF;
|
|
|
|
*data_ptr++ = (value >> 8) & 0xFF;
|
|
|
|
*data_ptr++ = (value >> 16) & 0xFF;
|
|
|
|
*data_ptr++ = (value >> 24) & 0xFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8 get_input_bit (uint16 slave_no,uint8 module_index)
|
|
|
|
{
|
|
|
|
/* Get the the startbit position in slaves IO byte */
|
|
|
|
uint8 startbit = ec_slave[slave_no].Istartbit;
|
2015-11-04 20:02:33 +08:00
|
|
|
/* Mask bit and return boolean 0 or 1 */
|
2014-11-25 23:10:29 +08:00
|
|
|
if (*ec_slave[slave_no].inputs & BIT (module_index - 1 + startbit))
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int16 get_output_int16(uint16 slave_no,uint8 module_index)
|
|
|
|
{
|
|
|
|
int16 return_value;
|
|
|
|
uint8 *data_ptr;
|
|
|
|
|
|
|
|
/* Get the IO map pointer from the ec_slave struct */
|
|
|
|
data_ptr = ec_slave[slave_no].outputs;
|
|
|
|
/* Move pointer to correct module index */
|
|
|
|
data_ptr += module_index * 2;
|
|
|
|
/* Read value byte by byte since all targets can handle misaligned
|
|
|
|
* addresses
|
|
|
|
*/
|
|
|
|
return_value = *data_ptr++;
|
|
|
|
return_value += (*data_ptr++ << 8);
|
|
|
|
|
|
|
|
return return_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_output_int16 (uint16 slave_no, uint8 module_index, int16 value)
|
|
|
|
{
|
|
|
|
uint8 *data_ptr;
|
|
|
|
/* Get the IO map pointer from the ec_slave struct */
|
|
|
|
data_ptr = ec_slave[slave_no].outputs;
|
|
|
|
/* Move pointer to correct module index */
|
|
|
|
data_ptr += module_index * 2;
|
|
|
|
/* Read value byte by byte since all targets can handle misaligned
|
|
|
|
* addresses
|
|
|
|
*/
|
|
|
|
*data_ptr++ = (value >> 0) & 0xFF;
|
|
|
|
*data_ptr++ = (value >> 8) & 0xFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8 get_output_bit (uint16 slave_no,uint8 module_index)
|
|
|
|
{
|
|
|
|
/* Get the the startbit position in slaves IO byte */
|
|
|
|
uint8 startbit = ec_slave[slave_no].Ostartbit;
|
2015-11-04 20:02:33 +08:00
|
|
|
/* Mask bit and return boolean 0 or 1 */
|
2014-11-25 23:10:29 +08:00
|
|
|
if (*ec_slave[slave_no].outputs & BIT (module_index - 1 + startbit))
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_output_bit (uint16 slave_no, uint8 module_index, uint8 value)
|
|
|
|
{
|
|
|
|
/* Get the the startbit position in slaves IO byte */
|
|
|
|
uint8 startbit = ec_slave[slave_no].Ostartbit;
|
|
|
|
/* Set or Clear bit */
|
|
|
|
if (value == 0)
|
|
|
|
*ec_slave[slave_no].outputs &= ~(1 << (module_index - 1 + startbit));
|
|
|
|
else
|
|
|
|
*ec_slave[slave_no].outputs |= (1 << (module_index - 1 + startbit));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern tt_sched_t * tt_sched[];
|
|
|
|
|
|
|
|
char IOmap[128];
|
|
|
|
int dorun = 0;
|
|
|
|
|
|
|
|
uint8_t load1s, load5s, load10s;
|
|
|
|
uint32_t error_counter = 0;
|
|
|
|
|
|
|
|
void tt_error (uint32_t task_ix);
|
|
|
|
void tt_error (uint32_t task_ix)
|
|
|
|
{
|
|
|
|
error_counter++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void my_cyclic_callback (void * arg)
|
|
|
|
{
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
stats_get_load (&load1s, &load5s, &load10s);
|
|
|
|
rprintp ("Processor load was %d:%d:%d (1s:5s:10s) with TT errors: %d\n",
|
|
|
|
load1s, load5s, load10s,error_counter);
|
|
|
|
task_delay(20000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void read_io (void * arg)
|
|
|
|
{
|
2015-11-04 20:02:33 +08:00
|
|
|
/* Function connected to cyclic TTOS task
|
2014-11-25 23:10:29 +08:00
|
|
|
* The function is executed cyclic according
|
|
|
|
* sceduel specified in schedule.tt
|
|
|
|
*/
|
|
|
|
*pPORTFIO_SET = BIT (6);
|
|
|
|
/* Send and receive processdata
|
|
|
|
* Note that you need som synchronization
|
|
|
|
* case you modifey IO in local application
|
|
|
|
*/
|
|
|
|
ec_send_processdata();
|
|
|
|
ec_receive_processdata(EC_TIMEOUTRET);
|
|
|
|
*pPORTFIO_CLEAR = BIT (6);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void simpletest(void *arg)
|
|
|
|
{
|
|
|
|
|
|
|
|
char *ifname = arg;
|
|
|
|
int cnt, i, j;
|
|
|
|
|
|
|
|
*pPORTFIO_DIR |= BIT (6);
|
|
|
|
|
|
|
|
rprintp("Starting simple test\n");
|
|
|
|
|
|
|
|
/* initialise SOEM */
|
|
|
|
if (ec_init(ifname))
|
|
|
|
{
|
|
|
|
rprintp("ec_init succeeded.\n");
|
2015-11-04 20:02:33 +08:00
|
|
|
|
2014-11-25 23:10:29 +08:00
|
|
|
/* find and auto-config slaves */
|
|
|
|
if ( ec_config_init(FALSE) > 0 )
|
|
|
|
{
|
|
|
|
rprintp("%d slaves found and configured.\n",ec_slavecount);
|
|
|
|
|
|
|
|
/* Check network setup */
|
|
|
|
if (network_configuration())
|
|
|
|
{
|
|
|
|
/* Run IO mapping */
|
|
|
|
ec_config_map(&IOmap);
|
|
|
|
|
|
|
|
rprintp("Slaves mapped, state to SAFE_OP.\n");
|
|
|
|
/* wait for all slaves to reach SAFE_OP state */
|
|
|
|
ec_statecheck(0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE);
|
|
|
|
|
|
|
|
/* Print som information on the mapped network */
|
|
|
|
for( cnt = 1 ; cnt <= ec_slavecount ; cnt++)
|
|
|
|
{
|
|
|
|
rprintp("\nSlave:%d\n Name:%s\n Output size: %dbits\n Input size: %dbits\n State: %d\n Delay: %d[ns]\n Has DC: %d\n",
|
|
|
|
cnt, ec_slave[cnt].name, ec_slave[cnt].Obits, ec_slave[cnt].Ibits,
|
|
|
|
ec_slave[cnt].state, ec_slave[cnt].pdelay, ec_slave[cnt].hasdc);
|
|
|
|
rprintp(" Configured address: %x\n", ec_slave[cnt].configadr);
|
|
|
|
rprintp(" Outputs address: %x\n", ec_slave[cnt].outputs);
|
|
|
|
rprintp(" Inputs address: %x\n", ec_slave[cnt].inputs);
|
|
|
|
|
|
|
|
for(j = 0 ; j < ec_slave[cnt].FMMUunused ; j++)
|
|
|
|
{
|
|
|
|
rprintp(" FMMU%1d Ls:%x Ll:%4d Lsb:%d Leb:%d Ps:%x Psb:%d Ty:%x Act:%x\n", j,
|
|
|
|
(int)ec_slave[cnt].FMMU[j].LogStart, ec_slave[cnt].FMMU[j].LogLength, ec_slave[cnt].FMMU[j].LogStartbit,
|
|
|
|
ec_slave[cnt].FMMU[j].LogEndbit, ec_slave[cnt].FMMU[j].PhysStart, ec_slave[cnt].FMMU[j].PhysStartBit,
|
|
|
|
ec_slave[cnt].FMMU[j].FMMUtype, ec_slave[cnt].FMMU[j].FMMUactive);
|
|
|
|
}
|
|
|
|
rprintp(" FMMUfunc 0:%d 1:%d 2:%d 3:%d\n",
|
2017-05-25 16:11:15 +08:00
|
|
|
ec_slave[cnt].FMMU0func, ec_slave[cnt].FMMU1func, ec_slave[cnt].FMMU2func, ec_slave[cnt].FMMU3func);
|
2014-11-25 23:10:29 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
rprintp("Request operational state for all slaves\n");
|
|
|
|
ec_slave[0].state = EC_STATE_OPERATIONAL;
|
|
|
|
/* send one valid process data to make outputs in slaves happy*/
|
|
|
|
ec_send_processdata();
|
|
|
|
ec_receive_processdata(EC_TIMEOUTRET);
|
|
|
|
/* request OP state for all slaves */
|
|
|
|
ec_writestate(0);
|
|
|
|
/* wait for all slaves to reach OP state */
|
|
|
|
ec_statecheck(0, EC_STATE_OPERATIONAL, EC_TIMEOUTSTATE);
|
|
|
|
if (ec_slave[0].state == EC_STATE_OPERATIONAL )
|
|
|
|
{
|
|
|
|
rprintp("Operational state reached for all slaves.\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rprintp("Not all slaves reached operational state.\n");
|
|
|
|
ec_readstate();
|
|
|
|
for(i = 1; i<=ec_slavecount ; i++)
|
|
|
|
{
|
|
|
|
if(ec_slave[i].state != EC_STATE_OPERATIONAL)
|
|
|
|
{
|
|
|
|
rprintp("Slave %d State=0x%04x StatusCode=0x%04x\n",
|
|
|
|
i, ec_slave[i].state, ec_slave[i].ALstatuscode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-04 20:02:33 +08:00
|
|
|
|
2014-11-25 23:10:29 +08:00
|
|
|
/* Simple blinking lamps BOX demo */
|
|
|
|
uint8 digout = 0;
|
|
|
|
|
|
|
|
slave_EL4001_1.out1 = (int16)0x3FFF;
|
|
|
|
set_output_int16(EL4001_1,0,slave_EL4001_1.out1);
|
|
|
|
|
|
|
|
task_spawn ("t_StatsPrint", my_cyclic_callback, 20, 1024, (void *)NULL);
|
|
|
|
tt_start_wait (tt_sched[0]);
|
|
|
|
|
|
|
|
while(1)
|
|
|
|
{
|
|
|
|
dorun = 0;
|
|
|
|
slave_EL1008_1.in1 = get_input_bit(EL1008_1,1); // Start button
|
|
|
|
slave_EL1008_1.in2 = get_input_bit(EL1008_1,2); // Turnkey RIGHT
|
|
|
|
slave_EL1008_1.in3 = get_input_bit(EL1008_1,3); // Turnkey LEFT
|
|
|
|
|
|
|
|
/* (Turnkey MIDDLE + Start button) OR Turnkey RIGHT OR Turnkey LEFT
|
|
|
|
Turnkey LEFT: Light positions bottom to top. Loop, slow operation.
|
|
|
|
Turnkey MIDDLE: Press start button to light positions bottom to top. No loop, fast operation.
|
|
|
|
Turnkey RIGHT: Light positions bottom to top. Loop, fast operation.
|
|
|
|
*/
|
|
|
|
if (slave_EL1008_1.in1 || slave_EL1008_1.in2 || slave_EL1008_1.in3)
|
|
|
|
{
|
|
|
|
digout = 0;
|
|
|
|
/* *ec_slave[6].outputs = digout; */
|
|
|
|
/* set_output_bit(slave_name #,index as 1 output on module , value */
|
|
|
|
set_output_bit(EL2622_1,1,(digout & BIT (0))); /* Start button */
|
|
|
|
set_output_bit(EL2622_1,2,(digout & BIT (1))); /* Turnkey RIGHT */
|
|
|
|
set_output_bit(EL2622_2,1,(digout & BIT (2))); /* Turnkey LEFT */
|
|
|
|
set_output_bit(EL2622_2,2,(digout & BIT (3)));
|
|
|
|
set_output_bit(EL2622_3,1,(digout & BIT (4)));
|
|
|
|
set_output_bit(EL2622_3,2,(digout & BIT (5)));
|
|
|
|
|
|
|
|
while(dorun < 95)
|
|
|
|
{
|
|
|
|
dorun++;
|
|
|
|
|
|
|
|
if (slave_EL1008_1.in3)
|
|
|
|
task_delay(tick_from_ms(20));
|
|
|
|
else
|
|
|
|
task_delay(tick_from_ms(5));
|
|
|
|
|
|
|
|
digout = (uint8) (digout | BIT((dorun / 16) & 0xFF));
|
|
|
|
|
|
|
|
set_output_bit(EL2622_1,1,(digout & BIT (0))); /* LED1 */
|
|
|
|
set_output_bit(EL2622_1,2,(digout & BIT (1))); /* LED2 */
|
|
|
|
set_output_bit(EL2622_2,1,(digout & BIT (2))); /* LED3 */
|
|
|
|
set_output_bit(EL2622_2,2,(digout & BIT (3))); /* LED4 */
|
|
|
|
set_output_bit(EL2622_3,1,(digout & BIT (4))); /* LED5 */
|
|
|
|
set_output_bit(EL2622_3,2,(digout & BIT (5))); /* LED6 */
|
|
|
|
|
|
|
|
slave_EL1008_1.in1 = get_input_bit(EL1008_1,2); /* Turnkey RIGHT */
|
|
|
|
slave_EL1008_1.in2 = get_input_bit(EL1008_1,3); /* Turnkey LEFT */
|
|
|
|
slave_EL3061_1.in1 = get_input_int32(EL3061_1,0); /* Read AI */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
task_delay(tick_from_ms(2));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rprintp("Mismatch of network units!\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rprintp("No slaves found!\n");
|
|
|
|
}
|
|
|
|
rprintp("End simple test, close socket\n");
|
|
|
|
/* stop SOEM, close socket */
|
|
|
|
ec_close();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rprintp("ec_init failed");
|
|
|
|
}
|
|
|
|
rprintp("End program\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_osal_timer_timeout_us (const uint32 timeout_us)
|
|
|
|
{
|
|
|
|
osal_timert timer;
|
|
|
|
|
|
|
|
ASSERT (timeout_us > 4000);
|
|
|
|
|
|
|
|
osal_timer_start (&timer, timeout_us);
|
|
|
|
ASSERT (osal_timer_is_expired (&timer) == false);
|
|
|
|
osal_usleep (timeout_us - 2000);
|
|
|
|
ASSERT (osal_timer_is_expired (&timer) == false);
|
|
|
|
osal_usleep (4000);
|
|
|
|
ASSERT (osal_timer_is_expired (&timer));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_osal_timer (void)
|
|
|
|
{
|
|
|
|
test_osal_timer_timeout_us (10*1000); /* 10ms */
|
|
|
|
test_osal_timer_timeout_us (100*1000); /* 100ms */
|
|
|
|
test_osal_timer_timeout_us (1000*1000); /* 1s */
|
|
|
|
test_osal_timer_timeout_us (2000*1000); /* 2s */
|
|
|
|
}
|
|
|
|
|
|
|
|
#define USECS_PER_SEC 1000000
|
|
|
|
#define USECS_PER_TICK (USECS_PER_SEC / CFG_TICKS_PER_SECOND)
|
|
|
|
#ifndef ABS
|
|
|
|
#define ABS(x) ((x) < 0 ? -(x) : (x))
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int32 time_difference_us (const ec_timet stop, const ec_timet start)
|
|
|
|
{
|
|
|
|
int32 difference_us;
|
|
|
|
|
|
|
|
ASSERT (stop.sec >= start.sec);
|
|
|
|
if (stop.sec == start.sec)
|
|
|
|
{
|
|
|
|
ASSERT (stop.usec >= start.usec);
|
|
|
|
}
|
|
|
|
|
|
|
|
difference_us = (stop.sec - start.sec) * USECS_PER_SEC;
|
|
|
|
difference_us += ((int32)stop.usec - (int32)start.usec);
|
|
|
|
|
|
|
|
ASSERT (difference_us >= 0);
|
|
|
|
return difference_us;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test osal_current_time() by using it for measuring how long an osal_usleep()
|
|
|
|
* takes, in specified number of microseconds.
|
|
|
|
*/
|
|
|
|
static void test_osal_current_time_for_delay_us (const int32 sleep_time_us)
|
|
|
|
{
|
|
|
|
ec_timet start;
|
|
|
|
ec_timet stop;
|
|
|
|
int32 measurement_us;
|
|
|
|
int32 deviation_us;
|
|
|
|
const int32 usleep_accuracy_us = USECS_PER_TICK;
|
|
|
|
boolean is_deviation_within_tolerance;
|
|
|
|
|
|
|
|
start = osal_current_time ();
|
|
|
|
osal_usleep (sleep_time_us);
|
|
|
|
stop = osal_current_time ();
|
|
|
|
|
|
|
|
measurement_us = time_difference_us (stop, start);
|
|
|
|
deviation_us = ABS (measurement_us - sleep_time_us);
|
|
|
|
is_deviation_within_tolerance = deviation_us <= usleep_accuracy_us;
|
|
|
|
ASSERT (is_deviation_within_tolerance);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_osal_current_time (void)
|
|
|
|
{
|
|
|
|
test_osal_current_time_for_delay_us (0);
|
|
|
|
test_osal_current_time_for_delay_us (1);
|
|
|
|
test_osal_current_time_for_delay_us (500);
|
|
|
|
test_osal_current_time_for_delay_us (999);
|
|
|
|
test_osal_current_time_for_delay_us (USECS_PER_TICK);
|
|
|
|
test_osal_current_time_for_delay_us (USECS_PER_TICK-1);
|
|
|
|
test_osal_current_time_for_delay_us (USECS_PER_TICK+1);
|
|
|
|
test_osal_current_time_for_delay_us (2 * 1000 * 1000); /* 2s */
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <lwip/inet.h>
|
|
|
|
|
|
|
|
static void test_oshw_htons (void)
|
|
|
|
{
|
|
|
|
uint16 network;
|
|
|
|
uint16 host;
|
|
|
|
|
|
|
|
host = 0x1234;
|
|
|
|
network = oshw_htons (host);
|
|
|
|
ASSERT (network == htons (host));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_oshw_ntohs (void)
|
|
|
|
{
|
|
|
|
uint16 host;
|
|
|
|
uint16 network;
|
|
|
|
|
|
|
|
network = 0x1234;
|
|
|
|
host = oshw_ntohs (network);
|
|
|
|
ASSERT (host == ntohs (network));
|
|
|
|
}
|
|
|
|
|
|
|
|
int main (void)
|
|
|
|
{
|
|
|
|
test_oshw_htons ();
|
|
|
|
test_oshw_ntohs ();
|
|
|
|
test_osal_timer ();
|
|
|
|
test_osal_current_time ();
|
|
|
|
|
|
|
|
rprintp("SOEM (Simple Open EtherCAT Master)\nSimple test\n");
|
|
|
|
|
|
|
|
task_spawn ("simpletest", simpletest, 9, 8192, NULL);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|