|
本帖最后由 zhongshu_1988 于 2013-1-16 12:33 编辑
一、硬件:
开发板用的是微雪的open1768,lpc1768的芯片;
以太网物理芯片用的是DP83848;
二、驱动:
驱动用的是lpc官方驱动包:lpc175x_6x_cmsis_driver_library
三、方案:
我在测试接收以太网数据帧,用一台linux笔记本写了一个以太网帧发送程序,每隔一秒向开发板发送一个以太网帧。然后,设置断点,测试接收情况。
四、源文件:
1. emactest.c- #include "string.h"
- #include "crc32.h"
- #include "lpc17xx_emac.h"
- #include "lpc17xx_gpio.h"
- #include "lpc17xx_pinsel.h"
- #include "lpc17xx_libcfg.h"
- /*目标:接收一个以太网帧,然后把该帧发送回去*/
- /* This is the MAC address of LPC1768 */
- #define EMAC_ADDR12 0x00006666
- #define EMAC_ADDR34 0x00006666
- #define EMAC_ADDR56 0x00006666
- /* A pseudo destination MAC address is defined for
- * both TX_ONLY and BOUNCE_RX test */
- #define EMAC_DST_ADDR12 0x0000E386
- #define EMAC_DST_ADDR34 0x00006BDA
- #define EMAC_DST_ADDR56 0x00005000
- /* INTERNAL MACROS ----------------------------------------------- */
- #define TX_PACKET_SIZE 114
- #define MYMAC_1 ((EMAC_ADDR12 & 0xFF00) >> 8)
- #define MYMAC_2 ((EMAC_ADDR12 & 0xFF))
- #define MYMAC_3 ((EMAC_ADDR34 & 0xFF00) >> 8)
- #define MYMAC_4 ((EMAC_ADDR34 & 0xFF))
- #define MYMAC_5 ((EMAC_ADDR56 & 0xFF00) >> 8)
- #define MYMAC_6 ((EMAC_ADDR56 & 0xFF))
- /* PRIVATE VARIABLES ----------------------------------------------- */
- /* Global Tx Buffer data 应用程序发送缓冲区*/
- uint8_t __attribute__ ((aligned (4))) gTxBuf[TX_PACKET_SIZE + 0x10];
- /* Global Rx Buffer data 应用程序发送缓冲区*/
- uint8_t __attribute__ ((aligned (4))) gRxBuf[TX_PACKET_SIZE + 0x10];
- /* EMAC address */
- uint8_t EMACAddr[] = {MYMAC_6, MYMAC_5, MYMAC_4, MYMAC_3, MYMAC_2, MYMAC_1};
- /* Tx, Rx Counters */
- __IO uint32_t RXOverrunCount = 0;
- __IO uint32_t RXErrorCount = 0;
- __IO uint32_t TXUnderrunCount = 0;
- __IO uint32_t TXErrorCount = 0;
- __IO uint32_t RxFinishedCount = 0;
- __IO uint32_t TxFinishedCount = 0;
- __IO uint32_t TxDoneCount = 0;
- __IO uint32_t RxDoneCount = 0;
- __IO uint32_t ReceiveLength = 0;
- __IO Bool PacketReceived = FALSE;
- /************************** PRIVATE FUNCTON **********************************/
- /* Interrupt service routines */
- void ENET_IRQHandler (void);
- void PacketGen(uint8_t *txptr);
- void Usr_Init_Emac(void);
- /*----------------- INTERRUPT SERVICE ROUTINES --------------------------*/
- /*********************************************************************//**
- * @brief Ethernet service routine handler
- * @param[in] none
- * @return none
- **********************************************************************/
- void ENET_IRQHandler (void)
- {
- EMAC_PACKETBUF_Type RxDatbuf;
- uint32_t RxLen;
- /* EMAC Ethernet Controller Interrupt function. */
- uint32_t int_stat;
- // Get EMAC interrupt status
- while ((int_stat = (LPC_EMAC->IntStatus & LPC_EMAC->IntEnable)) != 0) {
- // Clear interrupt status
- LPC_EMAC->IntClear = int_stat;
- /* scan interrupt status source */
- /* ---------- receive overrun ------------*/
- if((int_stat & EMAC_INT_RX_OVERRUN))
- {
- RXOverrunCount++;
- }
- /*----------- receive error -------------*/
- /* Note:
- * The EMAC doesn't distinguish the frame type and frame length,
- * so, e.g. when the IP(0x8000) or ARP(0x0806) packets are received,
- * it compares the frame type with the max length and gives the
- * "Range" error. In fact, this bit is not an error indication,
- * but simply a statement by the chip regarding the status of
- * the received frame
- */
- if ((int_stat & EMAC_INT_RX_ERR))
- {
- if (EMAC_CheckReceiveDataStatus(EMAC_RINFO_RANGE_ERR) == RESET){
- RXErrorCount++;
- }
- }
- /* ---------- RX Finished Process Descriptors ----------*/
- if ((int_stat & EMAC_INT_RX_FIN))
- {
- RxFinishedCount++;
- }
- /* ---------- Receive Done -----------------------------*/
- /* Note: All packets are greater than (TX_PACKET_SIZE + 4)
- * will be ignore!
- */
- if ((int_stat & EMAC_INT_RX_DONE))
- {
- /* Packet received, check if packet is valid. */
- if (EMAC_CheckReceiveIndex()){
- if (!EMAC_CheckReceiveDataStatus(EMAC_RINFO_LAST_FLAG)){
- goto rel;
- }
- // Get data size, trip out 4-bytes CRC field, note that length in (-1) style format
- RxLen = EMAC_GetReceiveDataSize() - 3;
- // Note that packet added 4-bytes CRC created by yourself
- if ((RxLen > (TX_PACKET_SIZE + 4)) || (EMAC_CheckReceiveDataStatus(EMAC_RINFO_SYM_ERR))) {
- /* Invalid frame, ignore it and free buffer */
- goto rel;
- }
- ReceiveLength = RxLen;
- // Valid Frame, just copy it
- RxDatbuf.pbDataBuf = (uint32_t *)gRxBuf;
- RxDatbuf.ulDataLen = RxLen;
- EMAC_ReadPacketBuffer(&RxDatbuf);
- PacketReceived = TRUE;
- rel:
- /* Release frame from EMAC buffer */
- EMAC_UpdateRxConsumeIndex();
- }
- RxDoneCount++;
- }
- /*------------------- Transmit Underrun -----------------------*/
- if ((int_stat & EMAC_INT_TX_UNDERRUN))
- {
- TXUnderrunCount++;
- }
- /*------------------- Transmit Error --------------------------*/
- if ((int_stat & EMAC_INT_TX_ERR))
- {
- TXErrorCount++;
- }
- /* ----------------- TX Finished Process Descriptors ----------*/
- if ((int_stat & EMAC_INT_TX_FIN))
- {
- TxFinishedCount++;
- }
- /* ----------------- Transmit Done ----------------------------*/
- if ((int_stat & EMAC_INT_TX_DONE))
- {
- TxDoneCount++;
- }
- }
- }
- /*-------------------------PRIVATE FUNCTIONS-----------------------------------*/
- /*********************************************************************//**
- * @brief Create a perfect packet for TX
- * @param[in] pointer to TX packet
- * @return none
- **********************************************************************/
- void PacketGen( uint8_t *txptr )
- {
- int i;
- uint32_t crcValue;
- uint32_t BodyLength = TX_PACKET_SIZE - 14;
- /* Dest address */
- *(txptr+0) = EMAC_DST_ADDR56 & 0xFF;
- *(txptr+1) = (EMAC_DST_ADDR56 >> 0x08) & 0xFF;
- *(txptr+2) = EMAC_DST_ADDR34 & 0xFF;
- *(txptr+3) = (EMAC_DST_ADDR34 >> 0x08) & 0xFF;
- *(txptr+4) = EMAC_DST_ADDR12 & 0xFF;
- *(txptr+5) = (EMAC_DST_ADDR12 >> 0x08) & 0xFF;
- /* Src address */
- *(txptr+6) = EMAC_ADDR56 & 0xFF;
- *(txptr+7) = (EMAC_ADDR56 >> 0x08) & 0xFF;
- *(txptr+8) = EMAC_ADDR34 & 0xFF;
- *(txptr+9) = (EMAC_ADDR34 >> 0x08) & 0xFF;
- *(txptr+10) = EMAC_ADDR12 & 0xFF;
- *(txptr+11) = (EMAC_ADDR12 >> 0x08) & 0xFF;
- /* Type or length, body length is TX_PACKET_SIZE - 14 bytes */
- *(txptr+12) = BodyLength & 0xFF;
- *(txptr+13) = (BodyLength >> 0x08) & 0xFF;
- /* Skip the first 14 bytes for dst, src, and type/length */
- for ( i=0; i < BodyLength; i++ )
- {
- *(txptr+i+14) = 0x55;
- }
- // Calculate CRC
- crcValue = crc32_bfr( txptr, TX_PACKET_SIZE );
- // Add 4-byte CRC
- *(txptr+TX_PACKET_SIZE) = (0xff & crcValue);
- *(txptr+TX_PACKET_SIZE+1) = 0xff & (crcValue >> 8 );
- *(txptr+TX_PACKET_SIZE+2) = 0xff & (crcValue >> 16);
- *(txptr+TX_PACKET_SIZE+3) = 0xff & (crcValue >> 24);
- }
- /*********************************************************************//**
- * @brief User EMAC initialize
- * @param[in] none
- * @return none
- **********************************************************************/
- void Usr_Init_Emac(void)
- {
- /* EMAC configuration type */
- EMAC_CFG_Type Emac_Config;
- /* pin configuration */
- PINSEL_CFG_Type PinCfg;
- uint32_t i;
- /*
- * Enable P1 Ethernet Pins:
- * P1.0 - ENET_TXD0
- * P1.1 - ENET_TXD1
- * P1.4 - ENET_TX_EN
- * P1.8 - ENET_CRS
- * P1.9 - ENET_RXD0
- * P1.10 - ENET_RXD1
- * P1.14 - ENET_RX_ER
- * P1.15 - ENET_REF_CLK
- * P1.16 - ENET_MDC
- * P1.17 - ENET_MDIO
- */
- PinCfg.Funcnum = 1;
- PinCfg.OpenDrain = 0;
- PinCfg.Pinmode = 0;
- PinCfg.Portnum = 1;
- PinCfg.Pinnum = 0;
- PINSEL_ConfigPin(&PinCfg);
- PinCfg.Pinnum = 1;
- PINSEL_ConfigPin(&PinCfg);
- PinCfg.Pinnum = 4;
- PINSEL_ConfigPin(&PinCfg);
- PinCfg.Pinnum = 8;
- PINSEL_ConfigPin(&PinCfg);
- PinCfg.Pinnum = 9;
- PINSEL_ConfigPin(&PinCfg);
- PinCfg.Pinnum = 10;
- PINSEL_ConfigPin(&PinCfg);
- PinCfg.Pinnum = 14;
- PINSEL_ConfigPin(&PinCfg);
- PinCfg.Pinnum = 15;
- PINSEL_ConfigPin(&PinCfg);
- PinCfg.Pinnum = 16;
- PINSEL_ConfigPin(&PinCfg);
- PinCfg.Pinnum = 17;
- PINSEL_ConfigPin(&PinCfg);
- Emac_Config.Mode = EMAC_MODE_AUTO;
- Emac_Config.pbEMAC_Addr = EMACAddr;
- // Initialize EMAC module with given parameter
- while (EMAC_Init(&Emac_Config) == ERROR){
- // Delay for a while then continue initializing EMAC module
- for (i = 0x100000; i; i--);
- }
- // Enable all interrupt
- EMAC_IntCmd((EMAC_INT_RX_OVERRUN | EMAC_INT_RX_ERR | EMAC_INT_RX_FIN \
- | EMAC_INT_RX_DONE | EMAC_INT_TX_UNDERRUN | EMAC_INT_TX_ERR \
- | EMAC_INT_TX_FIN | EMAC_INT_TX_DONE), ENABLE);
- NVIC_SetPriority(ENET_IRQn, 0);
- NVIC_EnableIRQ(ENET_IRQn);
- }
- /*-------------------------MAIN FUNCTION------------------------------*/
- /*********************************************************************//**
- * @brief c_entry: Main EMAC program body
- * @param[in] None
- * @return int
- **********************************************************************/
- int c_entry (void)
- {
- /* Data Packet format */
- EMAC_PACKETBUF_Type DataPacket;
- uint8_t *txptr;
- //uint32_t j;
- /*BOUNCE_RX*/
- uint8_t *rxptr;
- NVIC_SetPriorityGrouping(4); //sets PRIGROUP to 3:2 (XXX:YY)
- // Init EMAC
- Usr_Init_Emac();
- //txptr = (uint8_t *)gTxBuf;
- /* pre-format the transmit packets */
- //PacketGen(txptr);
- /*BOUNCE_RX*/
- //copy just received data from RX buffer to TX buffer and send out
- txptr = (uint8_t *)gTxBuf;
- rxptr = (uint8_t *)gRxBuf;
- /*BOUNCE_RX*/
- while( 1 )
- {
- //LED_Blink(BLINK_LED_PIN);
- if ( PacketReceived == TRUE )
- {
- PacketReceived = FALSE;
- //Reverse Source and Destination, then copy the body
- memcpy( (uint8_t *)txptr, (uint8_t *)(rxptr+6), 6);
- memcpy( (uint8_t *)(txptr+6), (uint8_t *)rxptr, 6);
- memcpy( (uint8_t *)(txptr+12), (uint8_t *)(rxptr+12), (ReceiveLength - 12));
- //Send packet back
- DataPacket.pbDataBuf = (uint32_t *)txptr;
- DataPacket.ulDataLen = ReceiveLength;
- EMAC_WritePacketBuffer(&DataPacket);
- EMAC_UpdateTxProduceIndex();
- }
- }
- /* Transmit packets only */
- /*
- while ( 1 ) {
- txptr = (uint8_t *)gTxBuf;
- //_DBG_("Send packet");
- //LED_Blink(TX_LED_PIN);
- DataPacket.pbDataBuf = (uint32_t *)txptr;
- // Note that there're 4-byte CRC added
- DataPacket.ulDataLen = TX_PACKET_SIZE + 4;
- EMAC_WritePacketBuffer(&DataPacket);
- EMAC_UpdateTxProduceIndex();
- for ( j = 0; j < 0x200000; j++ ); //delay
- }
- */
- }
- int main(void)
- {
- return c_entry();
- }
复制代码 2. lpc17xx_emac.c
这个文件我没有任何改动。
3. 用于发送以太网帧的linux程序pf_packet_sock.c
在附件中。
五、遇到的问题
用JLINK调试开发板,当网口接收到一个以太网帧时,就会进入ENET_IRQHandler中断处理程序,清中断、检查中断类型等等,直到进入第123行语句,发现总是跳转到rel,这说明出现了一个“EMAC_RINFO_SYM_ERR”错误。我查了数据手册,说是“SymbolError,在接收过程中,PHY通过PHY接口报告有一个位错误”。我不明白为什么会出现这种错误。实际上,我尝试过把“EMAC_CheckReceiveDataStatus(EMAC_RINFO_SYM_ERR)”注释,那么程序就接收正常,之后我再把接收到的数据包发送到我台式机,通过抓包,我发现,此时抓到的数据帧与我发送的数据帧一样。这又说明我接收的数据帧没有什么问题。但为什么报EMAC_RINFO_SYM_ERR错误呢?很困惑,迷茫,希望各位能给点提示,谢谢了。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|