AnsweredAssumed Answered

MMU issue on MQX4.1 for Vybrid

Question asked by Dawei You Employee on Aug 30, 2015
Latest reply on Sep 7, 2015 by alejandrolozano

Hi team:

 

My customer found one MMU issue on MQX for vybrid, PLS check and confirm.

When they use Ethernet and SDHC driver together, for example FTP application, after running long period, they found SDHC card have 32bytes error data.

After disable L2 cache, the issue couldn't be reproduced.

 

they trace the code find that cache operation will call address translate function, _mmu_vtop, like below:

 

void _l2c310_cache_invalidate_line(void *addr)

{

    /* addr parameter can be virtual address and this cache work only with physical address */

    void   *pa = NULL; /* physical address pointer */

    if (_mmu_vtop(addr, &pa) == MQX_OK)

    {

        CA5L2C_reg7_inv_pa = (uint32_t)pa & (L2C_reg7_clean_pa_Index_MASK | L2C_reg7_clean_pa_Tag_MASK);

        /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and EB, are emptyDrain the STB. Operation complete when all buffers, LRB, LFB, STB, and EB, are empty */

        while (CA5L2C_reg7_cache_sync & L2C_reg7_cache_sync_C_MASK);

    }

}

 

But this function _mmu_vtop do not prevent code reentry, the result will bring wrong PA address, which maybe write data to wrong address.

So whether need to add prevention code, like     _mmu_lock(); to avoid this potential issue?

 

/*!

* \brief translate virtual address to physical address

*

* \param va

* \param pa

*

* \return MQX_OK or an error code

*/

_mqx_int _mmu_vtop(void *va, void  **pa)

{

    /* VA to PA translation with privileged read permission check  */

    MCR(15, 0, (uint32_t)va & 0xfffffc00, 7, 8, 0);

    /* Read PA register */

    MRC(15, 0, *(uint32_t*)pa, 7, 4, 0);

    /* First bit of returned value is Result of conversion(0 is successful translation) */

    if ((uint32_t)*pa & 0x01)

    {

        /* We can try write permission also */

        /* VA to PA translation with privileged write permission check  */

        MCR(15, 0, (uint32_t)va & 0xfffffc00, 7, 8, 1);

        /* Read PA register */

        MRC(15, 0, *(uint32_t*)pa, 7, 4, 0);

        /* First bit of returned value is Result of conversion(0 is successful translation) */

        if ((uint32_t)*pa & 0x01)

        {

            return MQX_INVALID_POINTER;

        }

    }

    /* complete address returning base + offset*/

    *pa = (void *) (((uint32_t)*pa & 0xfffff000) | ((uint32_t)va & 0x00000fff));

    return MQX_OK;

}

Outcomes