回复 4楼 kooking 的帖子
代码其中之一: //-----------------------------------------------------------------------------
// \file evmomapl138_emac.c
// \brief implementation of the emac/mdio driver for the OMAP-L138 EVM.
//
//-----------------------------------------------------------------------------
#include "stdio.h"
#include "string.h"
#include "os_cpu_isr.h"
#include "includes.h"
#include "inc/evmomapl138_emac.h"
#include "inc/types.h"
#include "evmomapl138.h"
#include "evmomapl138_timer.h"
#include "inc/ethernet_smsc.h"
#include "inc/evmomapl138_gpio.h"
#include "inc/evmomapl138_i2c_gpio.h"
#include "inc/evmomapl138_cdce913.h"
#include "evmomapl138_aintc.h" // add_ISR需要
#include "netif/etharp.h"
#include "Emac_des.h"
#include "ethernetif.h"
#ifndef USE_HDTIME_DLY
#define USTIMER_delay(x)
#endif //USE_HDTIME_DLY
#define MAX_POLLING_NUM (0x0FFFFFFF)
//-----------------------------------------------------------------------------
// Private Defines and Macros
//-----------------------------------------------------------------------------
// INTCONTROL >> INTPRESCALE , number of EMAC clk period within a 4 us time window
#define NUM_INTPRESCALE (4*SYSCLOCK4_HZ/1000000) //4/(1000000/SYSCLOCK4_HZ) , 4us
// mdio clock divide down value.
#define MDIO_CLK_FREQ_HZ (2000000) //2M HZ
#define MDIO_CLK_DIVISOR ((SYSCLOCK4_HZ / MDIO_CLK_FREQ_HZ) - 1)
// rx / tx desriptor memory offsets.
#define RX_DESC_OFFSET (0)
#define TX_DESC_OFFSET (0x1000)
//MII pinmux
#define PINMUX_MII_REG_0 (2)
#define PINMUX_MII_MASK_0 (0xFFFFFFF0)
#define PINMUX_MII_VAL_0 (0x88888880)
#define PINMUX_MII_REG_1 (3)
#define PINMUX_MII_MASK_1 (0xFFFFFFFF)
#define PINMUX_MII_VAL_1 (0x88888888)
//RMII pinmux
#define PINMUX_RMII_REG_0 (14)
#define PINMUX_RMII_MASK_0 (0xFFFFFF00)
#define PINMUX_RMII_VAL_0 (0x88888800)
#define PINMUX_RMII_REG_1 (15)
#define PINMUX_RMII_MASK_1 (0x000000FF)
#define PINMUX_RMII_VAL_1 (0x00000080)
//MDIO pinmux
#define PINMUX_MDIO_REG (4)
#define PINMUX_MDIO_MASK (0x000000FF)
#define PINMUX_MDIO_VAL (0x00000088)
//GPIO pinmux
#define PINMUX_MII_MDIO_EN_REG (6)
#define PINMUX_MII_MDIO_EN_MASK (0x000000F0)
#define PINMUX_MII_MDIO_EN_VAL (0x00000080)
//
#define EMAC_RMII_SPEED_100 (0x00008000)
//-----------------------------------------------------------------------------
// Private Static Variables
//-----------------------------------------------------------------------------
static uint8_t g_active_phy_id = 0x0; //我们选用的L138是phy_id是为0的
//-----------------------------------------------------------------------------
// Private Function Prototypes
//-----------------------------------------------------------------------------
static uint32_t initMdioPhy(void);
static uint8_t isLinkActive(uint8_t in_phy);
static uint16_t phyRegRead(uint8_t in_phy, uint8_t in_reg);
static void phyRegWrite(uint8_t in_phy, uint8_t in_reg, uint16_t in_data);
//----------------------------------------------------------------------------
//Public value definitions
//----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Public Function Definitions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// \brief initialize the EMAC and MDIO for use.
//
// \param none.
//
// \return uint32_t
// ERR_NO_ERROR - everything is ok...emac ready to use.
// ERR_INIT_FAIL - something happened during initialization.
//-----------------------------------------------------------------------------
uint32_t Lowlevel_Emac_Init(void)
{
uint32_t rtn = 0;
uint32_t i;
SYS_ARCH_DECL_PROTECT(sr);
SYS_ARCH_PROTECT(sr);
// reset emac module.
EMAC->SOFTRESET = 1;
while (EMAC->SOFTRESET != 0) {;}
//init emac control module
//----------------------------------------
// AddISR() -- configuration of the interrupt to the CPU.
//AINTC --Number34 core0 Receive Interrupt
AddISR(34,L138Ethif_RxHandler,(void *)0);
aintcRegs->SICR = 34; //clear index status
aintcRegs->CMR8 = 0x00170000;//(Sets channel map, system interrupt --> host channel interrupt )
aintcRegs->EISR = 34; //Enable Index Set Register
aintcRegs->SECR2 = 0x00000004; //34 status clear
//configure Tx Interrupt Handler
AddISR(35,L138Ethif_TxHandler,(void *)0);
aintcRegs->SICR = 35; //clear index status
aintcRegs->CMR8 = 0x18000000; //SETS CHannel map
aintcRegs->EISR = 35; //Enable Index Set Register
aintcRegs->SECR2 = 0x00000008; //clear 35 status register ...
// configure INTCONTORL , CnRXIMAX, CnTXIMAX,
EMAC_CTRL->INTCTL = (NUM_INTPRESCALE| 0x00000300);
EMAC_CTRL->C0RXIMAX = 2;
EMAC_CTRL->C0TXIMAX = 2;
//--& init emac module.
//------------------
// make sure emac control interrupts are disabled.
EMAC_CTRL->C0RXTHRESHEN = 0;
EMAC_CTRL->C1RXTHRESHEN = 0;
EMAC_CTRL->C2RXTHRESHEN = 0;
EMAC_CTRL->C0RXEN = 0;
EMAC_CTRL->C1RXEN = 0;
EMAC_CTRL->C2RXEN = 0;
EMAC_CTRL->C0TXEN = 0;
EMAC_CTRL->C1TXEN = 0;
EMAC_CTRL->C2TXEN = 0;
EMAC_CTRL->C0MISCEN = 0;
EMAC_CTRL->C1MISCEN = 0;
EMAC_CTRL->C2MISCEN = 0;
EVMOMAPL138_pinmuxConfig(PINMUX_MDIO_REG, PINMUX_MDIO_MASK, PINMUX_MDIO_VAL); //MDIO shared by both RMII and MII
// EVMOMAPL138_pinmuxConfig(PINMUX_MII_MDIO_EN_REG, PINMUX_MII_MDIO_EN_MASK, PINMUX_MII_MDIO_EN_VAL); //pinmux to select gpio bank2 pin6
//PINMUXING
EVMOMAPL138_pinmuxConfig(PINMUX_MII_REG_0, PINMUX_MII_MASK_0, PINMUX_MII_VAL_0);
EVMOMAPL138_pinmuxConfig(PINMUX_MII_REG_1, PINMUX_MII_MASK_1, PINMUX_MII_VAL_1);
SYSCONFIG->KICKR[0] = KICK0R_UNLOCK;
SYSCONFIG->KICKR[1] = KICK1R_UNLOCK;
CLRBIT(SYSCONFIG->CFGCHIP[3], 0x00000100); //select mii mode !
//as software reset consideration, do this here
EVMOMAPL138_lpscTransition(PSC1, DOMAIN0, LPSC_EMAC, PSC_ENABLE);
// clear MAC control register, receive control register, transmiter control register
EMAC->MACCONTROL = 0;
EMAC->RXCONTROL = 0;
EMAC->TXCONTROL = 0;
// init header descriptor pointer regs to 0.
for (i = 0; i < 8; i++)
{
EMAC->TXHDP[i] = 0;
EMAC->RXHDP[i] = 0;
}
// clear all statistic register
#ifndef BOOT
memset((uint8_t *)NET_STAT_REG_BASE, 0, NET_STAT_REG_NUM_BYTES);
#endif
// setup local MAC address, only channel 0 is valid.
// program all 8, only need to set MACADDRHI for index = 0.
// use duplicate address for all unused channels.
// TODO: read MAC address from SPI flash.
//写的顺序是MACINDEX, ADDRHI, ADDRLO,由于高40bits是共享的
//只用了通道0,EMAC->MACADDRLO = 0X000000506 |VALID|MATCHFILT
for (i = 1; i < 8; i++)
{
EMAC->MACINDEX = i;
EMAC->MACADDRHI = 0x42020304; //index -> hi -> lo
EMAC->MACADDRLO = 0x00000506;
}
EMAC->MACINDEX = 0;
EMAC->MACADDRHI = 0x42020304;
// channel bit = 0, match mac address = 1
EMAC->MACADDRLO = 0x00000506 | MACADDRLO_VALID | MACADDRLO_MATCHFILT;
// for use tx DMA descriptor configuration:
EMAC->MACSRCADDRHI = 0x42020304;
EMAC->MACSRCADDRLO = 0x00000506;
// initialize receive channel free buffer count regs, if buffer flow
// control is to be enabled.
// NOTE: this example does not use buffer flow control.
// enable unicast chan 0 only.
EMAC->RXUNICASTSET = 0x01;
// no multicast addresses, clear MAC address hash registers.
EMAC->MACHASH1 = 0;
EMAC->MACHASH2 = 0;
// 只允许broadcast的ARP数据包,和发给自己的包,以太网的其他数据不放入Memmory里去.
//但是我单独设置RxBroadEn却没有作用。
EMAC->RXMBPENABLE = 0;
SETBIT(EMAC->RXMBPENABLE, (RXBROADEN|RXCAFEN));
// EMAC->RXMBPENABLE = 0x01E02020; //enable reception of almost all frames inc error
//11. configure MACCONTROL (Don't set GMIIEN Bit)
SETBIT(EMAC->MACCONTROL, (RMIISPEED|FULLDUPLEX|TXPACE)); //RMII_SPEED,为了适应RMII
// 12. Clear all unused channel interrupt bits by writing the receive interrupt mask clear register
//(RXINTMASKCLEAR) and the transmit interrupt mask clear register (TXINTMASKCLEAR).
EMAC->RXINTMASKCLEAR |= 0xFE; //RX channel 0的中断不屏蔽
EMAC->TXINTMASKCLEAR |= 0xFE; //TX CH0 中断屏蔽
//13. Modify RXINTMASKSET, TXINTMASKSET,MACINTMASKSET
EMAC->RXINTMASKSET |= 0x01;
EMAC->TXINTMASKSET |= 0x01;
EMAC->MACINTMASKCLR = 0x03; //disabled host mask , stat interrupt
//14 init receive buffer offset and max length.
EMAC->RXBUFFEROFFSET = 0;
EMAC->RXMAXLEN = MAX_PACKET_SIZE;
// initialize receive/transmit descriptor list queues.
Emac_des_init(); //modify 04/18
//16 enable receive / transmit DMA controllers...set GMIIEN.
EMAC->RXCONTROL = 1;
EMAC->TXCONTROL = 1;
SETBIT(EMAC->MACCONTROL, GMIIEN );
#if 1 //文档说未经测试,删除貌似没效果啊,先不管它
SETBIT(EMAC->EMCONTROL, SOFT);
#endif
// -->& init mdio / phy, 再加上MAC中断
//-----------------
rtn = initMdioPhy();
// if (rtn != ERR_NO_ERROR)
// return (rtn);
SYS_ARCH_UNPROTECT(sr);
//17>Enable the device interrupt in EMAC control module registers CnRXTHRESHEN, CnRXEN, CnTXEN,
//and CnMISCEN. -- LP Add
EMAC_CTRL->C0RXEN = 1; //C0RXPULSE Is Enabled for RX channel 0
EMAC_CTRL->C0TXEN = 1; //C0TXPULSE IS enabled for tx channel 0
return (rtn);
}
//-----------------------------------------------------------------------------
// \brief power on the phy.
//
// \param none.
//
// \return uint32_t
// ERR_NO_ERROR - everything is ok...phy is on.
// ERR_FAIL - something happened and could not power on.
//-----------------------------------------------------------------------------
uint32_t EMAC_phyPowerOn(void)
{
uint32_t rtn;
uint16_t ctrl_reg;
ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);
if (!CHKBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN))
{
// phy is already on...nothing left to do.
#if DEBUG
printf("phy powered, basic ctrl reg: %04x\n", ctrl_reg);
#endif
rtn = ERR_NO_ERROR;
}
else
{
// clear power down bit and write back to phy.
CLRBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN);
phyRegWrite(g_active_phy_id, SMSC_REG_BASIC_CTRL, ctrl_reg);
// short delay, then read the reg back to verify loopback is enabled.
USTIMER_delay(500);
ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);
if (!CHKBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN))
{
// phy is powered...return success.
#if DEBUG
printf("phy powered, basic ctrl reg: %04x\n", ctrl_reg);
#endif
rtn = ERR_NO_ERROR;
}
else
{
// power down bit did not clear...return error.
#if DEBUG
printf("power down did not clear: %04x\n", ctrl_reg);
#endif
rtn = ERR_FAIL;
}
}
return (rtn);
}
//-----------------------------------------------------------------------------
// \brief power down the phy.
//
// \param none.
//
// \return uint32_t
// ERR_NO_ERROR - everything is ok...phy is powered down.
// ERR_FAIL - something happened and could not power down.
//-----------------------------------------------------------------------------
uint32_t EMAC_phyPowerDown(void)
{
uint32_t rtn;
uint16_t ctrl_reg;
ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);
if(CHKBIT(ctrl_reg, BASIC_CTRL_ISOLATE) && CHKBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN))
{
// phy is already powered down...nothing left to do.
#if DEBUG
printf("phy powered down, basic ctrl reg: %04x\n", ctrl_reg);
#endif
rtn = ERR_NO_ERROR;
}
else
{
// set power down bit and write back to phy.
SETBIT(ctrl_reg, BASIC_CTRL_ISOLATE | BASIC_CTRL_POWER_DOWN);
phyRegWrite(g_active_phy_id, SMSC_REG_BASIC_CTRL, ctrl_reg);
// short delay, then read the reg back to verify loopback is disabled.
USTIMER_delay(500);
ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);
if(CHKBIT(ctrl_reg, BASIC_CTRL_ISOLATE) && CHKBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN))
{
// phy is powered down...return success.
#if DEBUG
printf("phy powered down, basic ctrl reg: %04x\n", ctrl_reg);
#endif
rtn = ERR_NO_ERROR;
}
else
{
// power down bit did not set...return error.
#if DEBUG
printf("power down bit did not set: %04x\n", ctrl_reg);
#endif
rtn = ERR_FAIL;
}
}
return (rtn);
}
//-----------------------------------------------------------------------------
// \brief put the phy into loopback mode.
//
// \param none.
//
// \return uint32_t
// ERR_NO_ERROR - everything is ok...phy is in loopback mode.
// ERR_FAIL - something happened and could not enter loopback.
//-----------------------------------------------------------------------------
uint32_t EMAC_phyEnterLoopback(void)
{
uint32_t rtn;
uint16_t ctrl_reg;
ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);
rtn = ERR_NO_ERROR;
if (ctrl_reg & BASIC_CTRL_LOOPBACK)
{
// loopback is already enabled...nothing left to do.
#if DEBUG
printf("loopback enabled, basic ctrl reg: %04x\n", ctrl_reg);
#endif
rtn = ERR_NO_ERROR;
}
else
{
// set loopback bit and write back to phy.
ctrl_reg |= BASIC_CTRL_LOOPBACK;
phyRegWrite(g_active_phy_id, SMSC_REG_BASIC_CTRL, ctrl_reg);
// short delay, then read the reg back to verify loopback is enabled.
USTIMER_delay(500);
ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);
if (ctrl_reg & BASIC_CTRL_LOOPBACK)
{
// loopback is enabled...return success.
#if DEBUG
printf("loopback enabled , basic ctrl reg: %04x\n", ctrl_reg);
#endif
rtn = ERR_NO_ERROR;
}
else
{
// loopback bit did not get set...return error.
#if DEBUG
printf("loopback did not set: %04x\n", ctrl_reg);
#endif
rtn = ERR_FAIL;
}
}
return (rtn);
}
//-----------------------------------------------------------------------------
// \brief remove the phy from loopback mode.
//
// \param none.
//
// \return uint32_t
// ERR_NO_ERROR - everything is ok...phy is out of loopback mode.
// ERR_FAIL - something happened and could not disable loopback.
//-----------------------------------------------------------------------------
uint32_t EMAC_phyExitLoopback(void)
{
uint32_t rtn;
uint16_t ctrl_reg;
ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);
if (!(ctrl_reg & BASIC_CTRL_LOOPBACK))
{
// loopback is already disabled...nothing left to do.
#if DEBUG
printf("loopback disabled, basic ctrl reg: %04x\n", ctrl_reg);
#endif
rtn = ERR_NO_ERROR;
}
else
{
// clear loopback bit and write back to phy.
ctrl_reg &= ~BASIC_CTRL_LOOPBACK;
phyRegWrite(g_active_phy_id, SMSC_REG_BASIC_CTRL, ctrl_reg);
// short delay, then read the reg back to verify loopback is disabled.
USTIMER_delay(5);
ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);
if (!(ctrl_reg & BASIC_CTRL_LOOPBACK))
{
// loopback is disabled...return success.
#if DEBUG
printf("loopback disabled , basic ctrl reg: %04x\n", ctrl_reg);
#endif
rtn = ERR_NO_ERROR;
}
else
{
// loopback bit did not clear...return error.
#if DEBUG
printf("loopback did not clear: %04x\n", ctrl_reg);
#endif
rtn = ERR_FAIL;
}
}
return (rtn);
}
//-----------------------------------------------------------------------------
// Private Function Definitions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// initialize the mdio module and identify the active phy.
//-----------------------------------------------------------------------------
uint32_t initMdioPhy(void)
{
uint32_t i = 0;
uint16_t phy_reg;
// init the mdio regs.
MDIO->CONTROL = MDIO_CTRL_ENABLE |
MDIO_CTRL_FAULT |
MDIO_CTRL_FAULTENB |
MDIO_CLK_DIVISOR;
while (CHKBIT(MDIO->CONTROL, MDIO_CTRL_IDLE)) {;}
#if DEBUG_MDIO_LINK
// look for an active phy...takes up to 50 us for each phy to be checked.
//以下只是调试时有用,真正烧入程序中去时,是不行的,因为没插上网线,AddISR还要上的。
for (i = 0; i < MAX_POLLING_NUM; i++)
{
if (MDIO->ALIVE)
{
// at least one phy has acknowledged us...break the loop.
break;
}
USTIMER_delay(50); // polling , 采用polling方式,LP- delete
}
while(!(MDIO->ALIVE)); //还是没有找到PHY,它就在此处挂住
#else
while(!(MDIO->ALIVE)) //没有网线连接
{
i++;
if(i >= MAX_POLLING_NUM)
{
break;
}
}//只是为了延时让phy与PC自适应的时涞却??
#endif
//
g_active_phy_id = 0; //确实是个发生错误,现在可以读到PHY。
MDIO->USERPHYSEL0 = 0; //USERPHYSEL0 = 0,表示PHY0被选中监控。
#if DEBUG_MDIO_LINK
phy_reg = phyRegRead(g_active_phy_id,0x02); //phy-id,查看phyRegRead是否正确;
if(phy_reg != 0x0022) //不等则芯片焊错
{
while(1);
}
#endif
return (ERR_NO_ERROR);
}
//-----------------------------------------------------------------------------
// returns if the link is currently active...1 -> active, 0 -> not active.
//-----------------------------------------------------------------------------
uint8_t isLinkActive(uint8_t in_phy)
{
uint16_t status;
status = phyRegRead(in_phy, SMSC_REG_BASIC_STAT);
if (CHKBIT(status, BASIC_STAT_LINK_STAT))
return (1);
else
return (0);
}
//-----------------------------------------------------------------------------
// read a phy register using the MDIO.
//-----------------------------------------------------------------------------
uint16_t phyRegRead(uint8_t in_phy, uint8_t in_reg)
{
// make sure mdio is not busy.
while (CHKBIT(MDIO->USERACCESS0, USERACC_GO)) {}
MDIO->USERACCESS0 = USERACC_GO |
(in_reg << USERACC_SHIFT_REG) |
(in_phy << USERACC_SHIFT_PHY);
while (CHKBIT(MDIO->USERACCESS0, USERACC_GO)) {}
return ((uint16_t)(MDIO->USERACCESS0 & USERACC_MASK_DATA));
}
//-----------------------------------------------------------------------------
// write a phy register using the MDIO.
//-----------------------------------------------------------------------------
void phyRegWrite(uint8_t in_phy, uint8_t in_reg, uint16_t in_data)
{
// make sure mdio is not busy.
while (CHKBIT(MDIO->USERACCESS0, USERACC_GO)) {}
MDIO->USERACCESS0 = USERACC_GO |
USERACC_WRITE |
(in_reg << USERACC_SHIFT_REG) |
(in_phy << USERACC_SHIFT_PHY) |
in_data;
}
代码其中之二:
/** Emac_des.c
** 由于在接收的过程中,可能存在一定的descriptor 问题,同时在与pbuf结合的情况
** 也存在着一些问题,故作如下修改。
** 现在决定作如下修改:
************************************/
#include "includes.h"
#include "Emac_des.h"
#include "evmomapl138.h"
#include "lwip/def.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "lwip/opt.h"
#include "inc/evmomapl138_emac.h"
#include "etharp.h"
#include "ethernetif.h"
/* CPPI RAM size in bytes */
#ifndef SIZE_CPPI_RAM
#define SIZE_CPPI_RAM 0x2000 //8K, L138也一样
#endif
#define MAX_ALE_ENTRIES 1024
#define ENTRY_TYPE 0x30
#define ENTRY_TYPE_IDX 7
#define ENTRY_FREE 0
/* MDIO input and output frequencies in Hz */
#define MDIO_FREQ_INPUT 125000000
#define MDIO_FREQ_OUTPUT 1000000
//flag --> 一样的描述
#define CPDMA_BUF_DESC_OWNER 0x20000000
#define CPDMA_BUF_DESC_SOP 0x80000000
#define CPDMA_BUF_DESC_EOP 0x40000000
#define CPDMA_BUF_DESC_EOQ 0x10000000
#define MAX_TRANSFER_UNIT 1518 // Lp modified
#define PBUF_LEN_MAX MAX_TRANSFER_UNIT
#define MAX_RX_PBUF_ALLOC 20 //使用20个看看
#define MIN_PKT_LEN 60
/* Define those to better describe the network interface. */
#define IFNAME0 'e'
#define IFNAME1 'n'
/* TX Buffer descriptor data structure */
struct cpdma_tx_bd {
volatile struct cpdma_tx_bd *next;
volatile u32_t bufptr;
volatile u32_t bufoff_len;
volatile u32_t flags_pktlen;
/* 添加了一个这样的数据结构 */
volatile struct pbuf *pbuf;
}cpdma_tx_bd;
/* RX Buffer descriptor data structure */
struct cpdma_rx_bd {
volatile struct cpdma_rx_bd *next;
volatile u32_t bufptr;
volatile u32_t bufoff_len;
volatile u32_t flags_pktlen;
/*添加了pbuf数据结构*/
volatile struct pbuf *pbuf;
}cpdma_rx_bd;
/**为的是编程者更好的处理RX channel发生的事件。***/
struct rxch {
volatile struct cpdma_rx_bd *free_head;
volatile struct cpdma_rx_bd *active_head;
volatile struct cpdma_rx_bd *active_tail;
u32_t freed_pbuf_len;
}rxch;
/** 是TX Channel 更好的处理事件 ***/
struct txch {
volatile struct cpdma_tx_bd *free_head;
volatile struct cpdma_tx_bd *active_tail;
volatile struct cpdma_tx_bd *next_bd_to_process;
}txch;
/**
** 这个是整个EMAC的操作界面数据结构 -- 不需要
*/
struct emac_trif {
/* The tx/rx channels for the interface */
struct txch txch;
struct rxch rxch;
}emac_trif;
/*
** 初始化buffer descriptor
** 换了一个方式,用一个pbuf 链的方式来接收,免去拷贝。
*/
err_t
Emac_des_init( void )
{
u32_t num_bd, pbuf_cnt = 0;
volatile struct cpdma_tx_bd *curr_txbd, *last_txbd;
volatile struct cpdma_rx_bd *curr_bd, *last_bd;
struct txch *txch;
struct rxch *rxch;
struct pbuf *p, *q;
//初始化.... 结构体..
//struct emac_trif {
memset((u8_t *)&emac_trif, 0, sizeof(emac_trif));
//struct txch {
memset((u8_t *)&txch, 0, sizeof(txch));
//struct rxch
memset((u8_t *)&rxch, 0, sizeof(rxch));
//struct cpdma_rx_bd {
memset((u8_t *)&cpdma_rx_bd, 0, sizeof(cpdma_rx_bd));
//struct cpdma_tx_bd {
memset((u8_t *)&cpdma_tx_bd, 0, sizeof(cpdma_rx_bd));
//取出txch的地址,以便操作
txch = &(emac_trif.txch);
//EMAC_RAM_BASE是L138的buffer descriptor 所在CPPI RAM的起始地址
txch->free_head = (volatile struct cpdma_tx_bd*)(EMAC_RAM_BASE);
txch->next_bd_to_process = txch->free_head;
txch->active_tail = (volatile struct cpdma_tx_bd *)NULL;
//多少个buffer desc, tx_bd... 特意SIZE_CPPI_RAM/2
num_bd = (SIZE_CPPI_RAM >> 1) / sizeof(cpdma_tx_bd);
curr_txbd = txch->free_head;
/* Initialize all the TX buffer Descriptors */
while(num_bd--) {
curr_txbd->next = curr_txbd + 1;
curr_txbd->bufptr = 0; //初始化为0
curr_txbd->bufoff_len = 0; //也初始化为0
curr_txbd->flags_pktlen = 0;
curr_txbd->pbuf = 0;//现在还并没有pbuf要准备发送
last_txbd = curr_txbd;
curr_txbd = curr_txbd->next;
}
last_txbd->next = txch->free_head;
/* Initialize the descriptors for the RX channel */
rxch = &(emac_trif.rxch);
rxch->active_head = (volatile struct cpdma_rx_bd*)(curr_txbd + 1);
rxch->free_head = (volatile struct cpdma_rx_bd *)NULL;
rxch->freed_pbuf_len = 0;
num_bd = ((SIZE_CPPI_RAM >> 1) / sizeof(cpdma_rx_bd) - 1);
curr_bd = rxch->active_head;
last_bd = curr_bd;
/*
** 该驱动一个最大的不同就在此处,将接收的数据直接用DMA传送到pbuf,
** 以前我们都是用全局ram接收,而后拷贝至pbuf,还有一个不同就是
** 这里使用了EMAC部的CPPI_RAM空间,这样达到最好的效率。
** 但是为了考虑字节对齐的问题,还需要做点小小的修改
*/
while(pbuf_cnt < MAX_RX_PBUF_ALLOC) {//产生10个pbuf..供接收DMA传送
#if ETH_PAD_SIZE
p = pbuf_alloc(PBUF_RAW,(PBUF_LEN_MAX+ETH_PAD_SIZE), PBUF_POOL); //10 * 1500
pbuf_header(p, -ETH_PAD_SIZE); //向后移2个字节,接收过后,刚刚好
#endif //ETH_PAD_SIZE
pbuf_cnt++;
if(p != NULL) {
/* write the descriptors if there are enough numbers to hold the pbuf*/
if(((u32_t)pbuf_clen(p)) <= num_bd) {
// pbuf_clen(p)计算从p开始,pbuf链的长度
//如果pbuf_alloc产生比num_bd更大长度的描述符,那么就是个悲剧了。
for(q = p; q != NULL; q = q->next) {
curr_bd->bufptr = (u32_t)(q->payload); //buffer_ptr
curr_bd->bufoff_len = q->len; //buffoff & buffer_len
curr_bd->next = curr_bd + 1; //next buffer descriptor
curr_bd->flags_pktlen = CPDMA_BUF_DESC_OWNER; //flag set or clear
/* Save the pbuf */
curr_bd->pbuf = q;
last_bd = curr_bd;
curr_bd = curr_bd->next;
num_bd--;
}//for
}//if <= num_bd
/* free the allocated pbuf if no free descriptors are left */
else {
pbuf_free(p);
break;
}//else pbuf chain len > num_bd
}//if p != NULL
else {
break;
}//else p== NULL
}//while 产生10个
last_bd->next = (volatile struct cpdma_rx_bd *)NULL; //buff des chain 构造完成
rxch->active_tail = last_bd; //rxch控制着整个rxch的接收方式
EMAC->RXHDP[0] = (u32_t)(rxch->active_head); //add - lp
return ERR_OK;
}
/**
** 使用该rx_inhandler处理接收中断
** 每个pbuf链在处理之前必须要向前移ETH_PAD_SIZE个字节,以便4字节对齐
** 当你还要产生pbuf的时候,也要向后移ETH_PAD_SIZE个字节,以便接收。
* @param netif the lwip network interface structure for this ethernetif
* @return none
*/
void
Emac_rxint_handler(struct netif *netif) {
struct rxch *rxch;
volatile struct cpdma_rx_bd *curr_bd, *processed_bd, *curr_tail, *last_bd;
volatile struct pbuf *pbuf, *q, *new_pbuf;
u32_t ex_len = 0, len_to_alloc = 0;
u16_t tot_len;
// sitaraif = netif->state;
rxch = &(emac_trif.rxch);
//得到当前的rxch buffer desc
curr_bd = rxch->active_head;
last_bd = rxch->active_tail;
//pbuf链中,SOP只出现一次,但是curr_bd已将buffer链推向下一个可能出现
//SOP的开头,所以这种方式更加严谨和有效。
while(curr_bd->flags_pktlen & CPDMA_BUF_DESC_SOP) {
//用while是因为pbuf链来处理的
ex_len = 0;
len_to_alloc = 0;
//当OWNER被EMAC清掉的时候,EMAC就放弃了buff desc,可以做一些处理
if((curr_bd->flags_pktlen & CPDMA_BUF_DESC_OWNER)
!= CPDMA_BUF_DESC_OWNER) {
if(rxch->free_head == NULL) {
/* this bd chain will be freed after processing */
rxch->free_head = curr_bd;
}//if NULL
//得到该接收到packet_len的长度
tot_len = (curr_bd->flags_pktlen) & 0xFFFF;
//保存当前接收的起始pbuf
q = curr_bd->pbuf;
//以下循环体为了更新除pbuf->payload除外,在结构体pbuf中
//的len,tot_len数据
do {
//得到当前pbuf地址
pbuf = curr_bd->pbuf;
/* If the earlier pbuf ended, update the chain */
if(pbuf->next == NULL) {
pbuf->next = (struct pbuf*)(curr_bd->next)->pbuf;
} //if Null
//len_to_alloc , pbuf链中的len的总和
len_to_alloc += pbuf->len;
/* Update the len and tot_len fields for the pbuf in the chain*/
pbuf->len = (curr_bd->bufoff_len) & 0xFFFF; //当前pbuf长度
pbuf->tot_len = tot_len - ex_len ; //当前pbuf后的tot_len长度(含自己)
processed_bd = curr_bd; //处理中的desc
ex_len += pbuf->len;
curr_bd = curr_bd->next;
} while((processed_bd->flags_pktlen & CPDMA_BUF_DESC_EOP)
!= CPDMA_BUF_DESC_EOP);
/**
* Close the chain for this pbuf. A full packet is received in
* this pbuf chain. Now this pbuf can be given to upper layers for
* processing. The start of the pbuf chain is now 'q'.
*/
pbuf->next = (struct pbuf *)NULL;
//在q处理之前,需要加上ETH_PAD_SIZE个空间,以便4字节对齐
#if ETH_PAD_SIZE
if(q != NULL)
{
pbuf_header((struct pbuf *)q, ETH_PAD_SIZE);
#endif //ETH_PAD_SIZE
//为了节省中断的处理效率,这里节省时间,直接post msg给tcpip_thread
if((netif->input((struct pbuf *)q,netif)) != ERR_OK)
{
pbuf_free((struct pbuf *)q);
q = (volatile struct pbuf *)NULL;
}
#if ETH_PAD_SIZE
} //ETH_PAD_SIZE
#endif //ETH_PAD_SIZE
/* Acknowledge that this packet is processed */
// CPSWCPDMARxCPWrite(sitaraif->cpsw_cpdma_base, 0, (unsigned int)processed_bd);
EMAC->RXCP[0] = (u32_t)processed_bd;
rxch->active_head = curr_bd;
/**
* The earlier pbuf chain is freed from the upper layer. So, we need to
* allocate a new pbuf chain and update the descriptors with the pbuf info.
* To support chaining, the total length freed by the upper layer is tracked.
* Care should be taken even if the allocation fails.
*/
/**
* now len_to_alloc will contain the length of the pbuf which was freed
* from the upper layer
*/
rxch->freed_pbuf_len += len_to_alloc;
new_pbuf = pbuf_alloc(PBUF_RAW, ((rxch->freed_pbuf_len)+ETH_PAD_SIZE), PBUF_POOL);
/* Write the descriptors with the pbuf info till either of them expires */
if(new_pbuf != NULL) {
#if ETH_PAD_SIZE
pbuf_header((struct pbuf *)new_pbuf, -ETH_PAD_SIZE);
#endif //ETH_PAD_SIZE
curr_bd = rxch->free_head; //free_head,已经被释放的head,需要重新set
//以下循环体添加新的pbuf到curr_bd中去
for(q = new_pbuf; (q != NULL) && (curr_bd != rxch->active_head); q = q->next) {
curr_bd->bufptr = (u32_t)(q->payload);
/* no support for buf_offset. RXBUFFEROFFEST register is 0 */
curr_bd->bufoff_len = (q->len) & 0xFFFF;
curr_bd->flags_pktlen = CPDMA_BUF_DESC_OWNER;
rxch->freed_pbuf_len -= q->len;
/* Save the pbuf */
curr_bd->pbuf = q;
last_bd = curr_bd;
curr_bd = curr_bd->next;
}//for
/**
* At this point either pbuf expired or no rxbd to allocate. If
* there are no, enough rx bds to allocate all pbufs in the chain,
* free the rest of the pbuf
*/
if(q != NULL) {
pbuf_free((struct pbuf *)q);
}
curr_tail = rxch->active_tail;
last_bd->next = (volatile struct cpdma_rx_bd *)NULL;
curr_tail->next = rxch->free_head;
/**
* Check if the reception has ended. If the EOQ flag is set, the NULL
* Pointer is taken by the DMA engine. So we need to write the RX HDP
* with the next descriptor.
*/
if(curr_tail->flags_pktlen & CPDMA_BUF_DESC_EOQ) {
// CPSWCPDMARxHdrDescPtrWrite(sitaraif->cpsw_cpdma_base,
// (u32_t)(rxch->free_head), 0);
EMAC->RXHDP[0] = (u32_t)(rxch->free_head);
}//if EOQ
rxch->free_head = curr_bd;
rxch->active_tail = last_bd;
}//if new_pbuf
}//if OWNER
curr_bd = rxch->active_head;
//以下这句,L138未做要求.
// CPSWCPDMANumFreeBufSet(sitaraif->cpsw_cpdma_base, 0, 1);
// -----------括号不要删-------------------------------
}//While ....
//-------------------------------------------
// 以下在外面写
// CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_TX_PULSE);
// CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_RX_PULSE);
}
//---------------------------------------------------------------
//以下是发送部分
//---------------------------------------------------------------
/**
** 这个函数将pbuf链的数据发送给物理层,可能buffer_des连接多处,因为是
** pbuf链连接而成的
* @return None
**/
void Emac_transmit(struct pbuf *pbuf) {
struct pbuf *q;
struct txch *txch;
volatile struct cpdma_tx_bd *curr_bd, *active_head, *bd_end;
// 取地址。
txch = &(emac_trif.txch);
//得到可以使用的空闲head
curr_bd = txch->free_head;
//激活的head
active_head = curr_bd;
//更新该头的packet len 字段
curr_bd->flags_pktlen &= ~0xFFFF;
curr_bd->flags_pktlen |= pbuf->tot_len;
//交给EMAC之前,置位flags, SOP,OWNER
curr_bd->flags_pktlen |= (CPDMA_BUF_DESC_SOP | CPDMA_BUF_DESC_OWNER);
//把pbuf信息构建成buffer desc 链
for(q = pbuf; q != NULL; q = q->next) {
/* Intialize the buffer pointer and length */
curr_bd->bufptr = (u32_t)(q->payload);
curr_bd->bufoff_len = (q->len) & 0xFFFF;
bd_end = curr_bd;
curr_bd->pbuf = pbuf;
curr_bd = curr_bd->next;
}
//将buffer desc结尾
bd_end->next = (volatile struct cpdma_tx_bd *)NULL;
bd_end->flags_pktlen |= CPDMA_BUF_DESC_EOP;
//free_head指向下一个空的buff descriptor 处
txch->free_head = curr_bd;
//经过初始化之后,txch->active_tail指向NULL,但是发送buffer desc是一个
//单向的循环链表。所以这也是上面为什么bd_end->next要赋NULL值
if(txch->active_tail == NULL) {
// 第一次发送active_head
EMAC->TXHDP[0] = (u32_t)active_head;
}
/*
**第1次发送过后,假如发送完了,那么transmiter 将会halt,这样CPU在
**发送之前必须确认EOQ是否set,如果set,那么对于CPU来讲可以写HDP启动
**TXDMA发送了。
*/
else {
curr_bd = txch->active_tail;
curr_bd->next = active_head;
if(curr_bd->flags_pktlen & CPDMA_BUF_DESC_EOQ) {
//假如EOQ被EMAC set之后,就启动tx DMA
EMAC->TXHDP[0] = (u32_t)active_head;
}
}
txch->active_tail = bd_end;
}
/**
* This function will send a packet through the emac if the channel is
* available. Otherwise, the packet will be queued in a pbuf queue.
*
* @param netif the lwip network interface structure for this ethernetif
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
* @return ERR_OK if the packet could be sent
* an err_t value if the packet couldn't be sent
*
*/
err_t
OmapEmac_output(struct netif *netif, struct pbuf *p)
{
INT8U os_err = 0;
SYS_ARCH_DECL_PROTECT(lev);
//等待有效的信号量才能发送
// OSSemPend(TxCmpSem, 1000, &os_err); // --LP , 2012/04/28 DLT
/**
* This entire function must run within a "critical section" to preserve
* the integrity of the transmit pbuf queue.
*
*/
SYS_ARCH_PROTECT(lev);
//在选择发送之前,要调整p->payload的两字节,因为它们不能发送出去
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE);
#endif
/* adjust the packet length if less than minimum required */
if(p->tot_len < MIN_PKT_LEN) {
p->tot_len = MIN_PKT_LEN;
p->len = MIN_PKT_LEN;
}
/**
* Bump the reference count on the pbuf to prevent it from being
* freed till we are done with it.
*
*/
pbuf_ref(p);
//Emac物理层的发送。DMA 用了TX中断的方式
Emac_transmit(p);
/* Return to prior interrupt state and return. */
SYS_ARCH_UNPROTECT(lev);
return ERR_OK;
}
/**
** lower level 已经启动DMA发送了吗,这里是为了软件清掉SOP和EOP,然后就是pbuf
** 链表的回收。
* @param netif the lwip network interface structure for this ethernetif
* @return none
*/
void
Emac_txint_handler(struct netif *netif) {
struct txch *txch;
volatile struct cpdma_tx_bd *curr_bd, *next_bd_to_process;
//取txch结构体的地址
txch = &(emac_trif.txch);
//下一待处理的buff des, next_bd_to_process被初始化为(EMAC_RAM_BASE)
next_bd_to_process = txch->next_bd_to_process;
// 用curr_bd来处理
curr_bd = next_bd_to_process;
/* Check for correct start of packet */
while((curr_bd->flags_pktlen) & CPDMA_BUF_DESC_SOP) {
/* Make sure that the transmission is over */
while((curr_bd->flags_pktlen & CPDMA_BUF_DESC_OWNER)
== CPDMA_BUF_DESC_OWNER);
/* Traverse till the end of packet is reached */
while(((curr_bd->flags_pktlen) & CPDMA_BUF_DESC_EOP) != CPDMA_BUF_DESC_EOP) {
curr_bd = curr_bd->next;
}//while(!EOP)
next_bd_to_process->flags_pktlen &= ~(CPDMA_BUF_DESC_SOP);
curr_bd->flags_pktlen &= ~(CPDMA_BUF_DESC_EOP);
/**
* If there are no more data transmitted, the next interrupt
* shall happen with the pbuf associated with the free_head
*/
if(curr_bd->next == NULL) {
txch->next_bd_to_process = txch->free_head;
}
else {
txch->next_bd_to_process = curr_bd->next; //接着处理下一帧数据包
}
//写TXCP[],该帧数据包已经写完
// CPSWCPDMATxCPWrite(sitaraif->cpsw_cpdma_base, 0, (u32_t)curr_bd);
EMAC->TXCP[0] = (u32_t)curr_bd;
pbuf_free((struct pbuf *)curr_bd->pbuf);
// LINK_STATS_INC(link.xmit);
next_bd_to_process = txch->next_bd_to_process;
curr_bd = next_bd_to_process;
}
//发送信号量给发送部分保证发送的完整性。
// OSSemPost(TxCmpSem); //--lp , 2012/04/28 delete,查看效果。
//在外面写的
// CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_TX_PULSE);
// CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_RX_PULSE);
}
/********************* this file is end ****************************/
代码其中之三:
/**************************************************************************
* *
* PROJECT : TMON (Transparent monitor) *
* *
* MODULE : LWIP.c *
* *
* AUTHOR : Michael Anburaj *
* URL : http://geocities.com/michaelanburaj/ *
* EMAIL: michaelanburaj@hotmail.com *
* *
* PROCESSOR : Any *
* *
* Tool-chain : gcc *
* *
* DESCRIPTION : *
* LwIP master source file. *
* *
**************************************************************************/
#include "tcpip.h"
#include "ethernetif.h"
#include "netconf.h"
/* ********************************************************************* */
/* Global definitions */
netif_t main_net;
/* ********************************************************************* */
/* File local definitions */
/* ********************************************************************* */
/**
*** 初始化LwIP的协议栈
*/
void LwIP_Init( void )
{
struct ip_addr ipaddr;
struct ip_addr netmask;
struct ip_addr gw;
tcpip_init(NULL, NULL);
/** 在此处初始化IP地址 **/
IP4_ADDR(&ipaddr,192,168,1,88); //该宏需要执行的!
IP4_ADDR(&netmask,255,255,255,0);
IP4_ADDR(&gw,192,168,0,1);
MEMCPY(main_net.name,"glzn",4);
#if LWIP_NETIF_HOSTNAME
main_net.hostname = GetHostName();
#endif
/* - netif_add(struct netif *netif, struct ip_addr *ipaddr,
struct ip_addr *netmask, struct ip_addr *gw,
void *state, err_t (* init)(struct netif *netif),
err_t (* input)(struct pbuf *p, struct netif *netif))
Adds your network interface to the netif_list. Allocate a struct
netif and pass a pointer to this structure as the first argument.
Give pointers to cleared ip_addr structures when using DHCP,
or fill them with sane numbers otherwise. The state pointer may be NULL.
The init function pointer must point to a initialization function for
your ethernet netif interface. The following code illustrates it's use.*/
netif_add(&main_net, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);
/* Registers the default network interface.*/
netif_set_default(&main_net); //可以删除 --2012/02/02, netif_default
/* When the netif is fully configured this function must be called.*/
netif_set_up(&main_net); //this functional
}
/* ********************************************************************* */
代码其中之四:
//主程序
//修改成适应LwIP v140的协议,此为系统main主函数
#include
#include
#include "dspint.h"
#include "sample.h"
#include "edma.h"
#include "norflash.h"
#include "evmomapl138.h"
#include "evmomapl138_gpio.h"
#include "evmomapl138_uart.h"
#include "evmomapl138_rtc.h"
#include "io.h"
#include "fpga_emifa.h"
#include "test_fpga.h"
//推荐的任务堆栈区大小为2048 OS_STK,即8192 byte
#define COMMON_STACK_LEN 2048
//给各个任务分配的堆栈区
OS_STK TaskLWIPStk[COMMON_STACK_LEN];
OS_STK TaskAppMainStk[COMMON_STACK_LEN];
OS_STK TaskMMIStk[COMMON_STACK_LEN];
OS_STK TaskFpgaUPPStk[COMMON_STACK_LEN];
OS_STK TaskFpgaEMIFAStk[COMMON_STACK_LEN * 32];
//OS_STK TaskTestStk[COMMON_STACK_LEN];
//各个任务进程主函数
void TaskAppMain(void *pd);
void TaskMMI(void *pd);//通过upp总线刷液晶数据,触发dsp中断,启动upp发送
extern void TaskLWIP(void *p_arg); //TaskLWIP任务
//extern void TaskTest(void *pd);
int main()
{
//初始化中断向量
OS_CPU_InitExceptVect();
//初始化uC/OS-II实时内核
OSInit();
//创建系统主进程任务(放在最高优先级,包括装置定值、参数自检测,并作为其他任务的WatchDog。)
OSTaskCreate(TaskAppMain, (void *)0, (OS_STK*)&TaskAppMainStk[COMMON_STACK_LEN-1], 2);
//启动操作系统内核
OSStart();
}
//系统主进程任务
void TaskAppMain(void *pd)
{
unsigned char ucErr;
tmr0_init();
GPIOInit();
chipint_init();
memset((unsigned char *)TaskLWIPStk, 0, (COMMON_STACK_LEN*sizeof(OS_STK)));
//初始化由Lwip任务堆栈开辟的堆栈区域
//INT8U enledflag = /;
//INT32U counter = 0;
//创建任务
//OSTaskCreate(TaskFPGA_UPP, (void *)0, (OS_STK*)&TaskFpgaUPPStk[COMMON_STACK_LEN-1], 11);
// OSTaskCreate(TaskFPGA_EMIFA, (void *)0, (OS_STK*)&TaskFpgaEMIFAStk[COMMON_STACK_LEN-1], 12);
// OSTaskCreate(TaskMMI, (void *)0, (OS_STK*)&TaskMMIStk[COMMON_STACK_LEN-1], 13);
//OSTaskCreate(TaskTest, (void *)0, (OS_STK*)&TaskTestStk[COMMON_STACK_LEN-1],100);
OSTaskCreate(TaskLWIP,(void *)0,(OS_STK *)&TaskLWIPStk[COMMON_STACK_LEN -1],10);
while(1)
{
/*asm(" nop");
counter++;
if(counter >=20)
{
enledflag ^=0x01;
inb(ARM_DSP_CMD) = enledflag;
DspintArmtrip(DSPINTTYPE_2);
counter = 0;
}
if(enledflag == 0)
{
ledchange();
}*/
// OSTimeDly(500);
// OSMboxPend(RxCntMbox,0,&ucErr);
OSTimeDly(1000);
asm(" nop");
}
}
//
#define SHAREMMI_ADR (0x80000200) //共享液晶显示数据区地址
#define MMI_LNUM (240) //液晶显示一屏数据的行数目
#define MMI_LBYTE (40) //液晶显示一屏数据的行字节数目320/8
#define MMI_DATALEN (MMI_LNUM*MMI_LBYTE) //液晶显示缓冲区长度
#define SHARERAW_ADR (0x8002800) //共享原始数据区地址
#define SHAREMEA_ADR (0x8001f000) //共享测量结果区地址
//显存
#define LCD_XSIZE (320) // X方向像素
#define LCD_YSIZE (240) // Y方向像素
#define LCDMLEN ((LCD_XSIZE*LCD_YSIZE)/8)
INT8U LcdMemory[LCDMLEN];
void loadMMIdata()
{
INT8U *pobject;
INT16U i;
static INT8U showdata = 0;
static INT8U changeflag = 0;
changeflag++;
if(changeflag==6)
{
changeflag=0;
showdata++;
}
pobject =LcdMemory;//(INT8U*)SHAREMMI_ADR;
if(showdata == 0)
{
for(i=0;i
{
*pobject++ = (i+1)&0xff;
}
}
else
{
for(i=0;i
{
*pobject++ = showdata;
}
}
}
void TaskMMI(void *pd)
{
while(1)
{
//pushus(0);
//loadMMIdata();
//EDMA0config(0,(void*)LcdMemory,(void*)SHAREMMI_ADR,LCDMLEN);
//pushus(1);
RelayTest();
OSTimeDly(100);
}
}
代码其中之五:
/* main.c
** test lwip
***************************************************/
#include
#include "evmomapl138.h"
#include
#include
#include
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/netif.h"
#include "lwip/tcpip.h"
#include "lwip.h"
// LwIP task stk Information
/**
** DEBUG Information
****************************************************/
/**
** global value
***************************************************/
/**
** function decl
**************************************************/
static void BSP_Init(void );
void tcpip_init_done(void *arg);
/* App_LwipTask
**
************************************************************************/
void TaskLWIP(void *parg)
{
//加载网卡驱动
//加载L138本身自带的EMAC驱动
//Lwip_v140使用lwip.c处理初始化网口的信息,主任务只要调用lwip_Init()即可
LwIP_Init();
while(1)
{
OSTimeDly(2000);
}
}
/* BSP_Init()
** 配置启动的时钟,貌似omapL138_app/boot.asm 中
** 有初始化STACK等配置,但是没有见到其内有时钟配置,工程初始化时也没有发现。
** 故要初始化PLL
********************************************/
void BSP_Init(void)
{
EVMOMAPL138_Init();
}
我贴了一些代码,请看看帮帮忙,我真不知道该如何解决啦... 复制代码