EtherCAT-8 从站代码移植-FSMC

硬件平台:STM32F103 + AX58100

AX58100 提供两种过程数据接口 (PDI),Local Bus 接口和 SPI Slave 接口,可通过这些接口将 AX58100 连接到外部 MCU/以支持 EtherCAT 功能。

上一章内容写了SPI接口,本章对LocalBus接口进行介绍,和上章重复的部分就不在叙述。LocalBus为并行通讯方式,相对于SPI,通讯速率更高,最高可到100Mbit/s,适用于传输数量较大的情况。LocalBus支持8bit或16bit并行数据,与MCU的FSMC或FMC外设接口连接,本文以16bit数据传输、FSMC外设接口为例。

1、硬件连接

注意,AX58100的地址线LA0接地,LA1:13连接至MCU的ADR0:12。

2、MCU配置

2.1 时钟

2.2 FSMC

  • 片选 NE1~NE4任意选择
  • 内存类型:SRAM
  • 地址位数,AX58100有14根地址线,此处填14 bits
  • 数据位数:16bits
  • 非同步模式
  • 取消勾选Byte enable
  • Extended mode设置为Disabled,FSMC自动使用模式A对SRAM进行操作,SRAM的读写操作速度基本相同,所以读写操作可以使用相同的时序参数,无需使用扩展模式单独设置读时序和写时序
  • 时序,三个参数:地址建立时间、数据建立时间和总线翻转时间,需要结合芯片读写时序具体设置

2.2.1 FSMC控制SRAM的时序

模式A的读写时序,如下图。

该图表示一个存储器操作周期由地址建立周期(ADDSET)、数据建立周期(DATAST)以及2个HCLK周期组成。在地址建立周期中,地址线发出要访问的地址, 数据掩码信号线指示出要读取地址的高、低字节部分,片选信号使能存储器芯片;地址建立周期结束后读使能信号线发出读使能信号, 接着存储器通过数据信号线把目标数据传输给FSMC,FSMC把它交给内核。

写时序类似,区别是它的一个存储器操作周期仅由地址建立周期(ADDSET)和数据建立周期(DATAST)组成, 且在数据建立周期期间写使能信号线发出写信号,接着FSMC把数据通过数据线传输到存储器中。

2.2.2 localBus的时序要求

结合FSMC和localBus的时序要求,参数配置如下:

总线翻转时间:在NOR FLASH存储器中,地址线与数据线可以分时复用,总线转换周期就是指总线在这两种状态间切换需要的延时,防止冲突,控制其它存储器时这个参数无效,配置为0即可。

地址建立时间:

地址就绪至读使能的时间:TADR_BHE_setup (>0)

地址就绪至写使能的时间:TADR_BHE_DATA_setup(>6.5 ns) - TWR_active(>8.5 ns)

数据建立时间:

读使能至数据有效的时间:Tread(<300 ns) +TBUSY_to_DATA_valid(< -15 ns)

写使能至写使能结束的时间:TWR_active(>8.5 ns)

即 (ADDSET+1) > 0, 8.5ns < (DATAST+1) < 285ns ,FSMC的时钟周期是1/72Mhz = 13.9ns,所以设置ADDSET = 0,DATAST = 10即满足要求。

其他定时器和外部中断配置与上一章SPI接口一致。

3.软件接口

软件接口可以在ssc工具生成的mcihw.h/c(SSC->Hardware选项的MCI_HW置1)文件上修改。

mcihw.h

#ifndef _MCIHW_H_
#define _MCIHW_H_


/*-----------------------------------------------------------------------------------------
------
------    Includes
------
-----------------------------------------------------------------------------------------*/
#include  "esc.h"



/*-----------------------------------------------------------------------------------------
------
------    Defines and Types
------
-----------------------------------------------------------------------------------------*/
#define ESC_PDI_BASEADDR     ((UINT32)0x60000000)  //Bank1_SRAMx_ADDR



/*---------------------------------------------
-    hardware timer settings
-----------------------------------------------*/


/*---------------------------------------------
-    Interrupt and Timer defines
-----------------------------------------------*/


  #define HW_GetALEventRegister()                   (*(volatile UINT16 ESCMEM *)(ESC_PDI_BASEADDR+(ESC_AL_EVENT_OFFSET)))  /**< \brief Returns the first 16Bit of the AL Event register (0x220)*/
  #define HW_GetALEventRegister_Isr                 HW_GetALEventRegister  /**< \brief Returns the first 16Bit of the AL Event register (0x220).<br>Called from ISRs.*/

  #define HW_EscRead(pData,Address,Len)             ESCMEMCPY((MEM_ADDR *)(pData), (UINT16 *)(ESC_PDI_BASEADDR+((Address))), (Len)) /**< \brief Generic ESC (register and DPRAM) read access.*/
  #define HW_EscWrite(pData,Address,Len)            ESCMEMCPY((UINT16 *)(ESC_PDI_BASEADDR+(Address)), (MEM_ADDR *)(pData), (Len)) /**< \brief Generic ESC (register and DPRAM) write access.*/
  #define HW_EscReadIsr                             HW_EscRead  /**< \brief Generic ESC (register and DPRAM) read access.<br>Called for ISRs.*/
  #define HW_EscWriteIsr                            HW_EscWrite /**< \brief Generic ESC (register and DPRAM) write access.<br>Called for ISRs.*/

//#if ESC_32BIT_ACCESS
  #define HW_EscReadDWord(DWordValue, Address)      ((DWordValue) = (*(volatile UINT32 *)(ESC_PDI_BASEADDR+(Address))))  /**< \brief 32Bit ESC read access*/
  #define HW_EscWriteDWord(DWordValue, Address)     ((*(volatile UINT32 *)(ESC_PDI_BASEADDR+(Address))) = (UINT32)(DWordValue))  /**< \brief 32Bit ESC write access*/
  #define HW_EscReadDWordIsr                        HW_EscReadDWord  /**< \brief Interrupt specific 32Bit ESC read access*/
  #define HW_EscWriteDWordIsr                       HW_EscWriteDWord  /**< \brief Interrupt specific 32Bit ESC write access*/
//#elif ESC_16BIT_ACCESS
  #define HW_EscReadWord(WordValue, Address)        ((WordValue) = (*(volatile UINT16 *)(ESC_PDI_BASEADDR+(Address))))  /**< \brief 16Bit ESC read access*/
  #define HW_EscWriteWord(WordValue, Address)       ((*(volatile UINT16 *)(ESC_PDI_BASEADDR+(Address))) = (UINT16)(WordValue))  /**< \brief 16Bit ESC write access*/
  #define HW_EscReadWordIsr                         HW_EscReadWord  /**< \brief Interrupt specific 16Bit ESC read access*/
  #define HW_EscWriteWordIsr                        HW_EscWriteWord  /**< \brief Interrupt specific 16Bit ESC write access*/
//#else
//  #define HW_EscReadByte(ByteValue,Address)	      ((ByteValue) = (*(volatile UINT8 *)(ESC_PDI_BASEADDR+(Address)))) /**< \brief 8Bit specific ESC (register and DPRAM) read access.*/
//  #define HW_EscWriteByte(ByteValue, Address)     ((*(volatile UINT8 *)(ESC_PDI_BASEADDR+(Address))) = (UINT8)(ByteValue))  /**< \brief 8Bit specific ESC (register and DPRAM) write access.*/
//  #define HW_EscReadByteIsr	                      HW_EscReadByte
//  #define HW_EscWriteByteIsr                      HW_EscWriteByte
//#endif

#define HW_EscReadMbxMem(pData,Address,Len)      ESCMBXMEMCPY((MEM_ADDR *)(pData), (UINT16 ESCMEM *)(ESC_PDI_BASEADDR+((Address))), (Len))  /**< \brief The mailbox data is stored in the local uC memory therefore the default read function is used.*/
#define HW_EscWriteMbxMem(pData,Address,Len)     ESCMBXMEMCPY(((UINT16 ESCMEM *)(ESC_PDI_BASEADDR+((Address)))),(MEM_ADDR *)(pData), (Len))  /**< \brief The mailbox data is stored in the local uC memory therefore the default write function is used.*/



#endif //_MCIHW_H_

/* ECATCHANGE_START(V5.11) ECAT10*/
#if defined(_MCIHW_H_) && (_MCIHW_H_ == 1)
/* ECATCHANGE_END(V5.11) ECAT10*/
    #define PROTO
#else
    #define PROTO extern
#endif


/*-----------------------------------------------------------------------------------------
------
------    Global variables
------
-----------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------
------
------    Global functions
------
-----------------------------------------------------------------------------------------*/
PROTO UINT8 HW_Init(void);
PROTO void  HW_Release(void);

#undef    PROTO
/** @}*/

mcihw.c

/*--------------------------------------------------------------------------------------
------
------    Includes
------
--------------------------------------------------------------------------------------*/
#include "ecat_def.h"

#include "ecatslv.h"


#include "mcihw.h"



#include "ecatappl.h"

#include  "gpio.h"
#include  "tim.h"

/*--------------------------------------------------------------------------------------
------
------    internal Types and Defines
------
--------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------
------
------    SPI defines/macros
------
-----------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------
------
------    Global Interrupt setting
------
-----------------------------------------------------------------------------------------*/
#define     ENABLE_GLOBAL_INT()       __enable_irq()
#define     DISABLE_GLOBAL_INT()      __disable_irq()
#define     ENABLE_AL_EVENT_INT       ENABLE_GLOBAL_INT()
#define     DISABLE_AL_EVENT_INT      DISABLE_GLOBAL_INT()
/*-----------------------------------------------------------------------------------------
------
------    ESC Interrupt
------
-----------------------------------------------------------------------------------------*/
//PDI_Isr
#define ENABLE_ESC_INT()    HAL_NVIC_EnableIRQ(EXTI0_IRQn)
#define DISABLE_ESC_INT()   HAL_NVIC_DienableIRQ(EXTI0_IRQn)
/*-----------------------------------------------------------------------------------------
------
------    SYNC0 Interrupt
------
-----------------------------------------------------------------------------------------*/
//Sync0_Isr
#define ENABLE_SYNCO_INT()    HAL_NVIC_EnableIRQ(EXTI9_5_IRQn)
#define DISABLE_SYNCO_INT()   HAL_NVIC_DienableIRQ(EXTI9_5_IRQn)
//Sync1_Isr
#define ENABLE_SYNC1_INT()    HAL_NVIC_EnableIRQ(EXTI4_IRQn)
#define DISABLE_SYNC1_INT()   HAL_NVIC_DienableIRQ(EXTI4_IRQn)
/*-----------------------------------------------------------------------------------------
------
------    Hardware timer
------
-----------------------------------------------------------------------------------------*/
#define START_ECAT_TIMER()    HAL_TIM_Base_Start_IT(&htim3)
#define STOP_ECAT_TIMER()     HAL_TIM_Base_Stop_IT(&htim3)

#define HW_GetTimer()         __HAL_TIM_GET_COUNTER(&htim3)
#define ECAT_TIMER_INC_P_MS   1000  //1ms定时器的计数值
/*-----------------------------------------------------------------------------------------
------
------    Configuration Bits
------
-----------------------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------------------
------
------    LED defines
------
-----------------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------------
------
------    internal Variables
------
----------------------------------------------------------------------------------


/*--------------------------------------------------------------------------------------
------
------    internal functions
------
--------------------------------------------------------------------------------------*/


/*--------------------------------------------------------------------------------------
------
------    exported hardware access functions
------
--------------------------------------------------------------------------------------*/


/
/**
\return     0 if initialization was successful

\brief    This function intialize the Process Data Interface (PDI) and the host controller.
*
UINT8 HW_Init(void)
{
/*ECATCHANGE_START(V5.11) EL9800 2*/
    UINT32 intMask;
/*ECATCHANGE_END(V5.11) EL9800 2*/


    /* make sure it's localbus */ 
    do
    {
        intMask = 0x00;
        HW_EscReadByte(intMask, ESC_PDI_CONTROL_OFFSET);
    } while (intMask != 0x08);

/*ECATCHANGE_START(V5.11) EL9800 2*/
    do
    {
        intMask = 0x93;
        HW_EscWriteDWord(intMask, ESC_AL_EVENTMASK_OFFSET);
        intMask = 0;
        HW_EscReadDWord(intMask, ESC_AL_EVENTMASK_OFFSET);

    } while (intMask != 0x93);

    intMask = 0x00;

    HW_EscWriteDWord(intMask, ESC_AL_EVENTMASK_OFFSET);

/*ECATCHANGE_END(V5.11) EL9800 2*/

#if AL_EVENT_ENABLED
   ENABLE_ESC_INT();
#endif

#if DC_SUPPORTED
   ENABLE_SYNC0_INT();
   ENABLE_SYNC1_INT();
#endif

#if ECAT_TIMER_INT
    START_ECAT_TIMER();
#endif

#if INTERRUPTS_SUPPORTED
    /* enable all interrupts */
    ENABLE_GLOBAL_INT();
#endif

    return 0;
}


/
/**
 \brief    This function shall be implemented if hardware resources need to be release
        when the sample application stops
*
void HW_Release(void)
{
    DISABLE_GLOBAL_INT();
}



/** @} */

其他内容与上一章SPI接口一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值