⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abl_arm922t_cp15_driver.c

📁 在sharp 404开发板的串口测试代码
💻 C
📖 第 1 页 / 共 2 页
字号:
   /* IAR CC includes some "intrinsic" functions to access ARM CP regs */
   status = __MRC(15, 0, 1, 0, 0);
#endif
    
    /* Is MMU enabled? */
    if ((status & ARM922T_MMU_CONTROL_M) == 0)
    {
        /* MMU is off; physical address is virtual address */
        return (void *)addr;
    }

    /* Get TLB base address */
    tlb = virtual_tlb_addr;
   
    /*******************************************************************
     * Search until found or all 4096 translation
     * table entries are examined.
     ******************************************************************/
    for (index = 0; index < ARM922T_TT_ENTRIES; index ++)
    {
        tlb_entry = tlb[index];
        switch (tlb_entry & ARM922T_L1D_TYPE_PG_SN_MASK)
        {
            case ARM922T_L1D_TYPE_FAULT:
                /* Invalid section or page, fault */
                break;

            case ARM922T_L1D_TYPE_CPAGE:
                /* Course page tables, loop through all entries */
                page_table = (UNS_32 *)(tlb_entry &
                    ARM922T_L2D_CP_BASE_MASK);
                for (index2 = 0; index2 < ARM922T_CPT_ENTRIES; index2++)
                {
                    level2 = page_table[index2];
                    if (level2)
                    {
                        virtual_addr = (void *)
                            cp15_decode_level2(level2, addr);

                        if (virtual_addr)
                        {
                            return virtual_addr;
                        }
                    }
                    break;
                }
                break;

            case ARM922T_L1D_TYPE_SECTION:
                /* Section type */
                /*******************************************************
                 * Section base -- upper 12 bits of entry is physical 
                 * memory base lower 20 bits of virtual address is 
                 * offset from that base
                 ******************************************************/
                if ((tlb_entry & ARM922T_L2D_SN_BASE_MASK) 
                    == (addr & ARM922T_L2D_SN_BASE_MASK))
                {
                    return (void *)((index << 20) |
                        (addr & ~(ARM922T_L2D_SN_BASE_MASK)));
                }
                break;

            case ARM922T_L1D_TYPE_FPAGE:
                /* Fine page tables, loop through entries */
                page_table = (UNS_32 *)(tlb_entry &
                    ARM922T_L2D_FP_BASE_MASK);
                for (index2 = 0; index2 < ARM922T_FPT_ENTRIES; index2++)
                {
                    level2 = page_table[index2];
                    if (level2)
                    {
                        virtual_addr = (void *)
                            cp15_decode_level2(level2, addr);

                        if (virtual_addr)
                        {
                            return virtual_addr;
                        }
                    }
                }
                break;

            default:
                break;
        }
    }

    return 0;
}

/***********************************************************************
 *
 * Function: cp15_force_cache_coherence
 *
 * Purpose:
 *     Force the CPU to recognize the block of code that was just
 *     written to memory between start_adr and end_adr even if caching
 *     and write buffering is on.
 *
 * Processing:
 *     Cache lines are 32-bytes (8 words); clean and invalidate each
 *     line of D-cache and invalidate each line of I-cache within the
 *     address range.
 *
 *     Invalidate the I-TLB within the the address range. The I-TLB has
 *     256 word granularity.
 *
 * Parameters: 
 *     start_adr:  The first address in the code block
 *     end_adr:    The last address in the code block
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
void cp15_force_cache_coherence(UNS_32 *start_adr,
                                UNS_32 *end_adr)
{
    register UNS_32 * addr;
   
    /*******************************************************************
     * Cache lines are 32-bytes (8 words); clean and invalidate each
     * line of D-cache and invalidate each line of I-cache within the
     * address range. Make sure addresses are 32-bit aligned.
     ******************************************************************/
    for (addr = (UNS_32 *)((UNS_32)start_adr & 0xFFFFFFE0);
         addr < end_adr;
         addr += 8)
    {
        /* p15 is MMU coprocessor, Cache OPS is c7, TLB OPS is c8 */
#ifdef __GNUC__
        asm ("MOV r0, %0" : : "r" (addr));
        /* Clean and Invalidate D-Cache single entry using MVA format */
        asm ("MCR p15, 0, r0, c7, c14, 1");
        /* Invalidate I-Cache single entry using MVA format */
        asm ("MCR p15, 0, r0, c7, c5, 1");
#endif
#ifdef __ghs__
        invalcache(addr);
#endif
#ifdef __arm
        __asm
        {
            MOV     r0, addr
            /* Clean and Invalidate D-Cache single entry using MVA 
               format */
            MCR     p15, 0, r0, c7, c14, 1
            /* Invalidate I-Cache single entry using MVA format */
            MCR     p15, 0, r0, c7, c5, 1
        }
#endif
#ifdef __ICCARM__
     
        /* Use IAR intrinsic functions */
        __MCR(15, 0, (UNS_32)addr, 7, 14, 1);
        __MCR(15, 0, (UNS_32)addr, 7, 5, 1);
#endif

    }
    /*******************************************************************
     * Invalidate the I-TLB within the the address range. The I-TLB has
     * 256 word granularity. Make sure addresses are '256 word' aligned.
     ******************************************************************/
    for (addr = (UNS_32 *)((UNS_32)start_adr & 0xFFFFFC00);
         addr < end_adr;
         addr += 256)
    {
#ifdef __GNUC__
        asm ("MOV r0, %0" : : "r" (addr));
        /* Invalidate I-TLB using MVA format */
        asm ("MCR p15, 0, r0, c8, c5, 1");
        asm ("NOP");
        asm ("NOP");
#endif
#ifdef __ghs__
        invaltlb(addr);
#endif
#ifdef __arm
        __asm
        {
            MOV     r0, addr
            /* Invalidate I-TLB using MVA format */
            MCR      p15, 0, r0, c8, c5, 1
            NOP
            NOP
        }
#endif
#ifdef __ICCARM__

		/* Invalidate I-TLB using MVA format */
		/* Use IAR intrinsic functions */
        __MCR(15, 0, (UNS_32)addr, 8, 5, 1);
        __no_operation();
        __no_operation();
#endif
    }
}

/***********************************************************************
 *
 * Function: cp15_init_mmu_trans_table
 *
 * Purpose: Initializes the MMU page table
 *
 * Processing:
 *     Return error if MMU is enabled. Return error if target
 *     Translation Table address is not 16K aligned. Clear the
 *     Translation Table area. Build the Translation Table from the
 *     initialization data in the Section Block array. Return no error.
 *
 * Parameters:  
 *      tt:    address of Translation Table in RAM.
 *      ttsbp: address of the beginning of the initialization array
 *
 * Outputs: None.
 *
 * Returns:  
 *     This function returns _ERROR when the MMU is enabled, or the
 *     target address is not 16K aligned. Otherwise, it returns
 *     _NO_ERROR.
 *
 * Notes: 
 *     This function is not intended to be used when the MMU is
 *     enabled.
 *
 **********************************************************************/
BOOL_32 cp15_init_mmu_trans_table(TRANSTABLE_T *tt,
                                  TT_SECTION_BLOCK_T *ttsbp)
{
    register UNS_32 control;
    UNS_32 idx;
    UNS_32 va_idx;
    UNS_32 pa_addr;
    UNS_32 *uiptr;
    UNS_32 ret = _NO_ERROR;

    /*******************************************************************
     * The following check returns an error if the MMU is enabled.
     * This condition is not necessarily an error, but an existing
     * Translation Table for an enabled MMU should not be overwritten
     * while the MMU is enabled. 
     ******************************************************************/

    /* Read the control register */
#ifdef __GNUC__
    asm ("MRC p15, 0, %0, c1, c0, 0" : "=r" (control));  
	/*xj 把c1 寄存器的值放到control 中, bit[0]控制mmu的使能*/
#endif
#ifdef __ghs__
    control = getstatus ();
#endif
#ifdef __arm
    __asm
    {
        MRC p15, 0, control, c1, c0, 0;
    }
#endif
#ifdef __ICCARM__
    /* Use IAR intrinsic functions */
    control = __MRC(15, 0, 1, 0, 0); 
#endif

    /* Exit if MMU is already enabeld */
    if ((control & ARM922T_MMU_CONTROL_M) != 0)
    {
        return (_ERROR);
    }

    /* Make sure table address is on a 16K boundary */
    if (((INT_32) tt & ~(ARM922T_TT_ADDR_MASK)) != 0)
    {
        return (_ERROR);
    }

    /*******************************************************************
     * Clear the entire Translation Table.
     * This results in L1D_TYPE_FAULT being the default for any
     * uninitialized entries.
     ******************************************************************/
    uiptr = (UNS_32 *) tt;
    for (idx = 0; idx < ARM922T_TT_ENTRIES; idx++)
        *uiptr++ = ARM922T_L1D_TYPE_FAULT;

    /* Build the translation table from user provided
       TT_SECTION_BLOCK_TYPE array */
    while (ttsbp->num_sections != 0)				///tt_init_basic
    {
        switch ((ttsbp->entry) & ARM922T_L1D_TYPE_PG_SN_MASK)
        {
            case ARM922T_L1D_TYPE_SECTION:
                va_idx = ttsbp->virt_addr >> 20;
                pa_addr = ttsbp->phys_addr & ARM922T_L2D_SN_BASE_MASK;
                for (idx = 0; idx < ttsbp->num_sections; idx++)
                {
                    tt->vidx[va_idx] = (pa_addr | ttsbp->entry);
                    va_idx++;
                    pa_addr += 0x100000;   ///add to 1M space
                }
                break;

            case (ARM922T_L1D_TYPE_CPAGE):    ///粗调页表
                va_idx = ttsbp->virt_addr >> 20;
                pa_addr = ttsbp->phys_addr & ARM922T_L2D_CP_BASE_MASK;
                for (idx = 0; idx < ttsbp->num_sections; idx++)
                {
                    tt->vidx[va_idx] = pa_addr | ttsbp->entry;
                    va_idx++;
                    pa_addr += 0x100000;
                }
                break;

            case ARM922T_L1D_TYPE_FAULT:
            default:
                break;
        }

        ttsbp++;
    }

    return ret;
}

/***********************************************************************
 *
 * Function: cp15_set_vmmu_addr
 *
 * Purpose: Set the virtual address of the MMU table
 *
 * Processing:
 *     Set the saved virtual MMU table address to the passed value.
 *
 * Parameters:  
 *      addr: Virtual address of start of MMU table
 *
 * Outputs: None.
 *
 * Returns: Nothing
 *
 * Notes:
 *     This function must be called if the driver MMU functions are
 *     being used. This should be set after the call to the
 *     cp15_init_mmu_trans_table() function.
 *
 **********************************************************************/
void cp15_set_vmmu_addr(UNS_32 *addr)
{
    virtual_tlb_addr = addr;
}

/***********************************************************************
 *
 * Function: cp15_get_ttb
 *
 * Purpose: Return the physical address of the MMU translation table
 *
 * Processing:
 *     Read the TTB register from coprocessor 15 and return it to the
 *     caller.
 *
 * Parameters: None
 *
 * Outputs: None.
 *
 * Returns: The base address of the MMU translation table
 *
 * Notes: None
 *
 **********************************************************************/
UNS_32 *cp15_get_ttb(void)
{
    register UNS_32 ttb;

#ifdef __GNUC__
    asm ("MRC p15, 0, %0, c2, c0, 0" : "=r" (ttb));
#endif
#ifdef __ghs__
    ttb = getttb();
#endif
#ifdef __arm
    __asm
    {
        MRC p15, 0, ttb, c2, c0, 0;
    }
#endif
#ifdef __ICCARM__
    /* use IAR CC intrinsic function to read CP15 reg */
	ttb = __MRC(15, 0, 2, 0, 0); 
#endif
    
    return (UNS_32 *) ttb;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -