This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

c6748 lwip 协议栈中使用 cache的问题



我现在使用c6748中使用emac的开发,软件配置128M的ddr,l1p  l1d l2p都用做cache,现在emac中的 接收中断和发送中断怎么使用cachewb  ();cacheinv();

来保证数据正常传输!

当不使用cache时,以太网是可以正常收发的!但是一使用cache收发数据就不正常!

在emac中断中怎样使用cache,这些有没有例程可以参考,谢谢!

  • 可以参考starterware里的cache例程C:\ti\C6748_StarterWare_1_20_04_01\examples\lcdkC6748\cache_mmu。
    http://processors.wiki.ti.com/index.php/StarterWare_01.20.01.01_User_Guide#Cache_Management

  • Zhang 先生:

               根据你的要求我把资料熟悉了下,现在更改如下:

    在main() 函数里加入以下使能cache

    {

    //关闭 emaci 的cppi 8k ram cache

    CacheDisableMAR((unsigned int)0x01E20000, (unsigned int)0x00002000); //EMACram //8k
    // 使能缓存 L1 及 L2
    CacheEnableMAR((unsigned int)0xC0000000, (unsigned int)0x08000000);    //ddr2 //128M
    CacheEnableMAR((unsigned int)0x80000000, (unsigned int)0x00020000);    //sharm //128k
    CacheEnable(L1DCFG_L1DMODE_32K | L1PCFG_L1PMODE_32K | L2CFG_L2MODE_256K);

    }

    在sitaraif.c中

    static void
    sitaraif_transmit(struct sitaraif *sitaraif, struct pbuf *pbuf) {
    struct pbuf *q;
    struct txch *txch;
    volatile struct cpdma_tx_bd *curr_bd, *active_head, *bd_end;

    txch = &(sitaraif->txch);

    /* Get the buffer descriptor which is free to transmit */
    curr_bd = txch->free_head;

    active_head = curr_bd;

    /* Update the total packet length */
    curr_bd->flags_pktlen &= ~0xFFFF;
    curr_bd->flags_pktlen |= pbuf->tot_len;

    /* Indicate the start of the packet */
    curr_bd->flags_pktlen |= (CPDMA_BUF_DESC_SOP | CPDMA_BUF_DESC_OWNER);

    /* Copy pbuf information into TX buffer descriptors */
    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;

    //新增加 cacheWB  回写

    CacheWB ((unsigned int) curr_bd->bufptr, curr_bd->bufoff_len);

    //
    curr_bd = curr_bd->next;
    }

    /* Indicate the end of the packet */
    bd_end->next = NULL;
    bd_end->flags_pktlen |= CPDMA_BUF_DESC_EOP;

    txch->free_head = curr_bd;


    /* For the first time, write the HDP with the filled bd */
    if(txch->active_tail == NULL) {
    CPSWCPDMATxHdrDescPtrWrite(sitaraif->cpsw_cpdma_base,
    (unsigned int)(active_head), 0);
    }

    /*
    * Chain the bd's. If the DMA engine, already reached the end of the chain,
    * the EOQ will be set. In that case, the HDP shall be written again.
    */
    else {
    curr_bd = txch->active_tail;
    curr_bd->next = active_head;

    if(curr_bd->flags_pktlen & CPDMA_BUF_DESC_EOQ) {
    /* Write the Header Descriptor Pointer and start DMA */
    CPSWCPDMATxHdrDescPtrWrite(sitaraif->cpsw_cpdma_base,
    (unsigned int)(active_head), 0);
    }
    }

    txch->active_tail = bd_end;
    }

    void
    sitaraif_rx_inthandler(struct netif *netif) {
    struct sitaraif *sitaraif;
    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 = &(sitaraif->rxch);

    /* Get the bd which contains the earliest filled data */
    curr_bd = rxch->active_head;
    last_bd = rxch->active_tail;

    /**
    * Process the descriptors as long as data is available
    * when the DMA is receiving data, SOP flag will be set
    */
    while(curr_bd->flags_pktlen & CPDMA_BUF_DESC_SOP) {
    ex_len = 0;
    len_to_alloc = 0;

    /* Start processing once the packet is loaded */
    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;
    }

    /* Get the total length of the packet. curr_bd points to the start
    * of the packet.
    */
    tot_len = (curr_bd->flags_pktlen) & 0xFFFF;

    /* Get the start of the pbuf queue */
    q = curr_bd->pbuf;

    do {
    /* Get the pbuf pointer which is associated with the current bd */
    pbuf = curr_bd->pbuf;

    /* If the earlier pbuf ended, update the chain */
    if(pbuf->next == NULL) {
    pbuf->next = (struct pbuf*)(curr_bd->next)->pbuf;
    }

    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->tot_len = tot_len - ex_len ;

    //新增
    CacheInv ((unsigned int) pbuf->payload, pbuf->len);
    //


    processed_bd = curr_bd;
    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 = NULL;

    /* Adjust the link statistics */
    LINK_STATS_INC(link.recv);

    /* Process the packet */
    if(ethernet_input((struct pbuf *)q, netif) != ERR_OK) {
    /* Adjust the link statistics */
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.drop);
    }

    /* Acknowledge that this packet is processed */
    CPSWCPDMARxCPWrite(sitaraif->cpsw_cpdma_base, 0, (unsigned int)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), PBUF_POOL);

    /* Write the descriptors with the pbuf info till either of them expires */
    if(new_pbuf != NULL) {
    curr_bd = rxch->free_head;

    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;
    }

    /**
    * 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 = 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);
    }

    rxch->free_head = curr_bd;
    rxch->active_tail = last_bd;
    }
    }
    curr_bd = rxch->active_head;

    CPSWCPDMANumFreeBufSet(sitaraif->cpsw_cpdma_base, 0, 1);

    }

    CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_TX_PULSE);
    CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_RX_PULSE);
    }

  • 以上更改,网络通信压根就不通

  • 关于怎么lwip怎么使用cache,有例程吗