原创 飞思卡尔MCF52259 FEC demo程序

2010-6-28 00:55 3390 11 12 分类: MCU/ 嵌入式

原文转自:http://user.qzone.qq.com/345630492?ptlang=2052


是最近我们组做mcf52259开发板过程中一个demo测试程序


MCF52259_FEC—Fast Ethernet Controller<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


  好久没写总结了,游戏一天现在也没什么状态干活,就来总结下近来的成果吧。


  调Coldfire的以太网花的时间比较长,以前一直以为这块很难,有种畏惧心理,现在回过头来看看,要是不加协议的话跟IICSPI以及串口也相差不到哪去。最大的体会就是以太网的速度快的惊人,而且发送、接收数据很智能。


  这次用的板子是我们自己做的开发板,主芯片MCF52259,标称最高主频<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />80M。呵呵,试过把它倍频到120M,依然正常工作!哈哈,没想到我们玩的也可以超频吧。它只有FEC即以太网控制器,并没有收发器模块,所以要外扩收发器PHY,这里用的是国家半导体的DP83848,给我的感觉依然是智能。支持10/100Mb/psMII……等等一大堆。


  FEC的功能给我的感觉就是智能地控制数据的收与发。当有数据发送时,只要把数据存到缓冲区内并置位发送描述符的Ready位,并告诉FEC发送数据就绪它就自动完成数据的发送,结束后FEC会自动将发送描述符的Ready位清0;当有数据发过来时它会检查是否有接收描述符的empty位为1,要有的话就把数据放到那个描述符对就的接收缓冲区中,并将接收描述符的empty位清零,以告诉我们接收数据完成。这里有个其它通信方式没有的东西,那就是发送、接收描述符了,因为以太网的速度非常快,需要要的接收、发送缓冲区都很大,FEC模块并没有这么大的存储空间,因此使用芯片的RAM作为缓冲区。描述符的功能就是用来描述缓冲区的各种状态、数据长度以及缓冲区在RAM中的起始位置,FEC就通过描述符来控制数据传输。


  就算不用协议,这块多多少少还是会涉及到一些协议方面的东西,要好好看资料了。而且后叙的工作还很多很多。


  下面就是FEC初始化及,发送接收数据不用协议裸跑的代码:


/*
*
初始化FEC,及接收发送描术符,系统MAC等
*/
void fec_init(uint8 mac_addr_fec[6])
{
 MCF_FEC_ECR=MCF_FEC_ECR_RESET;
 while(MCF_FEC_ECR&MCF_FEC_ECR_RESET)
 {
  ;
 }
 
 MCF_FEC_EIMR=MCF_FEC_EIMR_MASK_ALL;
 MCF_FEC_EIR=MCF_FEC_EIR_CLEAR_ALL;
 
 MCF_FEC_PALR=(uint32)(0
    |mac_addr_fec[0]<<24|mac_addr_fec[1]<<16
    |mac_addr_fec[2]<<8 |mac_addr_fec[3]);
 MCF_FEC_PAUR=(uint32)(0
    |mac_addr_fec[4]<<24|mac_addr_fec[5]<<16
    |MCF_FEC_PAUR_TYPE(0x8808));
 
 MCF_FEC_IALR=0;
 MCF_FEC_IAUR=0;
 MCF_FEC_GALR=0xFFFFFFFF;
 MCF_FEC_GAUR=0xFFFFFFFF;
//Set receive buffer size 
 MCF_FEC_EMRBR=MCF_FEC_EMRBR_R_BUF_SIZE(0x62);
 
 MCF_FEC_RCR=MCF_FEC_RCR_MAX_FL(1520)
      |MCF_FEC_RCR_MII_MODE
      |MCF_FEC_RCR_BC_REJ;
      //|MCF_FEC_RCR_PROM;
      //|MCF_FEC_RCR_DRT;
      
 MCF_FEC_TCR=MCF_FEC_TCR_FDEN;
 
//80/(16*2)=2.5M 
 MCF_FEC_MSCR=MCF_FEC_MSCR_MII_SPEED(16);
 
 BD_init();
 MCF_FEC_ERDSR=(uint32)&RxBDs[0];
 MCF_FEC_ETSDR=(uint32)&TxBDs[0];
 
 MCF_FEC_MIBC=MCF_FEC_MIBC_MIB_DISABLE;
 MCF_FEC_ECR=MCF_FEC_ECR_ETHER_EN;
 MCF_FEC_RDAR=MCF_FEC_RDAR_R_DES_ACTIVE;
 MCF_FEC_TDAR=MCF_FEC_TDAR_X_DES_ACTIVE;
}



/*
*src_data[]
为要发送的数据
*destAdd[6]
为目的MAC地址
*srcAdd[6]
这本地MAC地址
*lenType
为数据长度加类型
*len
为是要发送的数据Byte
*/
int8 FEC_FrameSend(uint8 src_data[],uint8 destAdd[6],uint8 srcAdd[6],uint16 lenType,uint16 len)
{
// uint8 i;
 vuint8 * TxdataAd;
 txbd_pt++;
 if(txbd_pt>=NUM_TXBDS) txbd_pt=0;
 while((TxBDs[txbd_pt].status&MCF_FEC_TxBD_R)==MCF_FEC_TxBD_R)
 {
  txbd_pt++;
  if(txbd_pt>=NUM_TXBDS) 
   txbd_pt=0;
 }
 TxdataAd=TxBDs[txbd_pt].dataAD;
 
 memcpy((uint8*)TxdataAd,(uint8*)destAdd,6);
 TxdataAd+=6;
 memcpy((uint8*)TxdataAd,(uint8*)srcAdd,6);
 TxdataAd+=6;
 *TxdataAd++=(uint8)(lenType>>8);
 *TxdataAd++=(uint8)lenType;
 memcpy((void*)TxdataAd,(void*)src_data,len);
 TxBDs[txbd_pt].length=(uint16)(len+14);
 TxBDs[txbd_pt].status|=0
        |MCF_FEC_TxBD_L
        |MCF_FEC_TxBD_TC
        |MCF_FEC_TxBD_R;
        
 MCF_FEC_TDAR=MCF_FEC_TDAR_X_DES_ACTIVE;
 
 return 0; 
}


//用查寻方式接收数据,接收到的数据放到dest_data[]
int8 FEC_FrameReceive(uint8 dest_data[],uint16 *len)
{
 vuint8* RxdataAd;
 rxbd_pt++;
 if(rxbd_pt>=NUM_RXBDS) rxbd_pt=0;
 while((RxBDs[rxbd_pt].status&MCF_FEC_RxBD_E)==MCF_FEC_RxBD_E)
 {
  rxbd_pt++;
  if(rxbd_pt>=NUM_RXBDS) rxbd_pt=0;
 }
 
 RxdataAd=RxBDs[rxbd_pt].dataAD;
 *len=RxBDs[rxbd_pt].length;
 
 memcpy((uint8*)dest_data,(uint8*)RxdataAd,*len);
 
 RxBDs[rxbd_pt].status|=MCF_FEC_RxBD_E;
 MCF_FEC_RDAR=MCF_FEC_RDAR_R_DES_ACTIVE;
 
 return 1;
}


void BD_init(void)
{
 uint8 i;
 
 RxBDs=(BD*)((uint32)(rxbd+16)&0xFFFFFFF0);
 TxBDs=(BD*)((uint32)(txbd+16)&0xFFFFFFF0);
 
 RxBuff=(uint8*)((uint32)(rxbuffer+16)&0xFFFFFFF0);
 TxBuff=(uint8*)((uint32)(txbuffer+16)&0xFFFFFFF0);
 
 for(i=0;i<NUM_RXBDS;i++)
 {
  RxBDs.status=(0|MCF_FEC_RxBD_E);
  RxBDs.length=0;
  RxBDs.dataAD=&RxBuff[i*RX_BUFF_SIZE];
 }
 RxBDs[NUM_RXBDS-1].status|=MCF_FEC_RxBD_W;
 
 for(i=0;i<NUM_TXBDS;i++)
 {
  TxBDs.status=(0
      |MCF_FEC_TxBD_L
      |MCF_FEC_TxBD_TC);
  TxBDs.length=0;
  TxBDs.dataAD=&TxBuff[i*TX_BUFF_SIZE];
 }
 TxBDs[NUM_TXBDS-1].status|=MCF_FEC_TxBD_W;
 
}


//用于数据copy
void memcpy(uint8* des,uint8* src,uint16 num)
{
 while(num>0)
 {
  *des++=*src++;
  num--;
 }
}


 


 
PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户1357320 2011-1-12 09:57

楼主好样的
相关推荐阅读
用户1361860 2012-06-28 23:44
Nicrosystem Freescale Kinetis教程---SDHC
这是研究生翻译的SDHC的中文文档,里面很多句子不通,但我现在没时间去修改了。先放出来,应该还是会有一点作用  ...
用户1361860 2012-06-26 12:39
Nicrosystem Freescale Kinetis教程--低功耗定时器
Freescale Kinetis内部集成了一个独特的低功耗定时器,它可以在系统处于低功耗模式下,仍然以极低功耗运行,可以用于在适当时候唤醒系统进入正常工作模式  ...
用户1361860 2012-06-24 22:11
Nicrosystem Freescale Kinetis教程----RTC实时时钟
Nicrosystem的飞思卡尔kinetis教程之片上RTC  ...
用户1361860 2012-06-22 10:21
TI C2000微控制器指南
这是官方的C2000的介绍,C2000做电机控制那是业界最好的。  ...
用户1361860 2012-06-20 23:52
Nicrosystem Freescale Kinetis教程--PIT定时器教程
这是PIT定时器的教程,PIT是 Kinetis支持的另一种定时器,相对于上一讲的flextimer要简单。 今晚赶到北京,到宾馆发一篇博客  ...
用户1361860 2012-06-19 13:15
Nicrosystem Freescale Kinetis教程--Flextimer教程
Kinetis的Flextimer定时器教程 kinetis集成了众多功能各异的定时器,flextimer是其中最为复杂的一个  ...
我要评论
1
11
关闭 站长推荐上一条 /3 下一条