forked from xuos/xiuos
				
			
		
			
				
	
	
		
			211 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			211 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright (c) 2020 AIIT XUOS Lab
 | 
						|
 * XiUOS is licensed under Mulan PSL v2.
 | 
						|
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
						|
 * You may obtain a copy of Mulan PSL v2 at:
 | 
						|
 *        http://license.coscl.org.cn/MulanPSL2
 | 
						|
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
						|
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
						|
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
						|
 * See the Mulan PSL v2 for more details.
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * @file adapter_ethercat.c
 | 
						|
 * @brief Implement the connection ethercat adapter function, reuse the ethernet implementations
 | 
						|
 * @version 1.1
 | 
						|
 * @author AIIT XUOS Lab
 | 
						|
 * @date 2021.10.15
 | 
						|
 */
 | 
						|
 | 
						|
#include <adapter.h>
 | 
						|
#include <ethercat.h>
 | 
						|
 | 
						|
#ifdef ADAPTER_HFA21_ETHERCAT
 | 
						|
extern AdapterProductInfoType Hfa21EthercatAttach(struct Adapter *adapter);
 | 
						|
#endif
 | 
						|
 | 
						|
#define ADAPTER_ETHERCAT_NAME "ethercat"
 | 
						|
 | 
						|
/**
 | 
						|
 * @description: clear the datagram in ethercat frame, do not free the frame itself, since it may be a memory space on stack
 | 
						|
 * @param frame - ethercat frame pointer
 | 
						|
 */
 | 
						|
void EcatClear(EcatFramePtr frame)
 | 
						|
{
 | 
						|
    EcatDatagramPtr datagram = frame->datagram;
 | 
						|
    while (datagram)
 | 
						|
    {
 | 
						|
        EcatDatagramPtr temp = datagram->next;
 | 
						|
        PrivFree(datagram->data);
 | 
						|
        PrivFree(datagram);
 | 
						|
        datagram = temp;
 | 
						|
    }
 | 
						|
    memset(frame, 0, sizeof(EcatFrame));
 | 
						|
    frame->header.length = 2; // 2 bytes for the ethercat header
 | 
						|
    frame->header.res = 1;
 | 
						|
    frame->header.type = 0b1001;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @description: receive data from adapter
 | 
						|
 * @param frame - ethercat frame pointer
 | 
						|
 * @param address - ethercat address
 | 
						|
 * @param data - data to be carried inside frame
 | 
						|
 * @param data_len - length of provided `data`
 | 
						|
 * @return success: 0, else return error code.
 | 
						|
 */
 | 
						|
int EcatAppend(EcatFramePtr frame, EcatAddress address, uint8_t *data, uint16_t data_len)
 | 
						|
{
 | 
						|
    EcatDatagramPtr datagram = frame->datagram;
 | 
						|
    if (!datagram)
 | 
						|
    {
 | 
						|
        datagram = PrivMalloc(sizeof(EcatDatagram));
 | 
						|
        if (!datagram)
 | 
						|
        {
 | 
						|
            printf("EcatAppend malloc error\n");
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        memset(datagram, 0, sizeof(EcatDatagram));
 | 
						|
        frame->datagram = datagram;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        while (datagram->next)
 | 
						|
        {
 | 
						|
            datagram = datagram->next;
 | 
						|
        }
 | 
						|
        datagram->header.m = 1; // indcate the datagram is not the last one
 | 
						|
        datagram->next = PrivMalloc(sizeof(EcatDatagram));
 | 
						|
        if (!datagram->next)
 | 
						|
        {
 | 
						|
            printf("EcatAppend malloc error\n");
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        memset(datagram->next, 0, sizeof(EcatDatagram));
 | 
						|
        datagram = datagram->next;
 | 
						|
    }
 | 
						|
    datagram->header.address = address;
 | 
						|
    datagram->header.length = data_len;
 | 
						|
    datagram->data = data;
 | 
						|
    datagram->work_counter++;
 | 
						|
    frame->header.length += sizeof(datagram->header) + data_len + sizeof(datagram->work_counter);
 | 
						|
    printf("EcatAppend change length to %d\n", frame->header.length);
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @description: find datagram for self and update its content
 | 
						|
 * @param frame - ethercat frame pointer
 | 
						|
 * @param address - ethercat address
 | 
						|
 * @param data - data to be carried inside frame
 | 
						|
 * @param data_len - length of provided `data`
 | 
						|
 * @return success: 0, else return error code.
 | 
						|
 */
 | 
						|
int EcatUpdate(EcatFramePtr frame, uint8_t *data, uint16_t data_len)
 | 
						|
{
 | 
						|
    EcatDatagramPtr datagram = frame->datagram;
 | 
						|
    if (!datagram)
 | 
						|
    {
 | 
						|
        printf("EcatUpdate error: null datagram.\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    while (datagram)
 | 
						|
    {
 | 
						|
        if (datagram->self)
 | 
						|
        {
 | 
						|
            datagram->header.length = data_len;
 | 
						|
            frame->header.length -= strlen(datagram->data);
 | 
						|
            datagram->data = data;
 | 
						|
            frame->header.length +=  data_len;
 | 
						|
            datagram->work_counter++;
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            datagram = datagram->next;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    printf("EcatUpdate error: cannot find datagram for node itself.\n");
 | 
						|
    return -2;
 | 
						|
}
 | 
						|
 | 
						|
static int AdapterEthercatRegister(struct Adapter *adapter)
 | 
						|
{
 | 
						|
    int ret = 0;
 | 
						|
 | 
						|
    strncpy(adapter->name, ADAPTER_ETHERCAT_NAME, NAME_NUM_MAX);
 | 
						|
 | 
						|
    adapter->net_protocol = IP_PROTOCOL;
 | 
						|
    adapter->adapter_status = UNREGISTERED;
 | 
						|
 | 
						|
    ret = AdapterDeviceRegister(adapter);
 | 
						|
    if (ret < 0)
 | 
						|
    {
 | 
						|
        printf("AdapterEthercat register error\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
int AdapterEthercatInit(void)
 | 
						|
{
 | 
						|
    int ret = 0;
 | 
						|
 | 
						|
    struct Adapter *adapter = PrivMalloc(sizeof(struct Adapter));
 | 
						|
    if (!adapter)
 | 
						|
    {
 | 
						|
        printf("AdapterEthercatInit malloc error\n");
 | 
						|
        PrivFree(adapter);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    memset(adapter, 0, sizeof(struct Adapter));
 | 
						|
 | 
						|
    ret = AdapterEthercatRegister(adapter);
 | 
						|
    if (ret < 0)
 | 
						|
    {
 | 
						|
        printf("AdapterEthercatInit register ethercat adapter error\n");
 | 
						|
        PrivFree(adapter);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef ADAPTER_HFA21_ETHERCAT
 | 
						|
    AdapterProductInfoType product_info = Hfa21EthercatAttach(adapter);
 | 
						|
    if (!product_info)
 | 
						|
    {
 | 
						|
        printf("AdapterEthercatInit hfa21 attach error\n");
 | 
						|
        PrivFree(adapter);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    adapter->product_info_flag = 1;
 | 
						|
    adapter->info = product_info;
 | 
						|
    adapter->done = product_info->model_done;
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/******************ethercat TEST*********************/
 | 
						|
extern int Hfa21EthercatSlaveTest(struct Adapter *adapter);
 | 
						|
extern int Hfa21EthercatMasterTest(struct Adapter *adapter);
 | 
						|
 | 
						|
int AdapterEthercatTest(void)
 | 
						|
{
 | 
						|
    struct Adapter *adapter = AdapterDeviceFindByName(ADAPTER_ETHERCAT_NAME);
 | 
						|
 | 
						|
#ifdef ADAPTER_HFA21_ETHERCAT
 | 
						|
#ifdef AS_ETHERCAT_SLAVE_ROLE
 | 
						|
    Hfa21EthercatSlaveTest(adapter);
 | 
						|
#else // AS_ETHERCAT_MASTER_ROLE
 | 
						|
    Hfa21EthercatMasterTest(adapter);
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_PARAM_NUM(0) | SHELL_CMD_DISABLE_RETURN, AdapterEthercatTest, AdapterEthercatTest, show adapter ethercat information);
 |