mmu.h File Reference


Detailed Description

MMU example application.

This file gives an example of using the MMU to manage the memory on AVR32 MCUs.

Author:
Atmel Corporation: http://www.atmel.com
Support email: avr32@atmel.com
$Name$
Revision
$RCSfile$
Date

Definition in file mmu.h.

#include <avr32/io.h>
#include "settings.h"

Include dependency graph for mmu.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  mmu_tlb_t
 Struct which defines options for operating on TLB entries. More...

Enumerations

enum  {
  MMU_ERROR = -1, MMU_OK = 0, MMU_ERROR_ARGUMENT = 1, MMU_TLB_MISS = 2,
  MMU_DISABLE = 0, MMU_ENABLE = 1, MMU_PRIVATE_VIRTUAL_MODE = 0, MMU_SHARED_VIRTUAL_MODE = 1,
  MMU_SEGMENTATION_OFF = 0, MMU_SEGMENTATION_ON = 1, MMU_TLB_TYPE_DATA = 0, MMU_TLB_TYPE_INSTRUCTION = 1,
  MMU_PAGE_SIZE_1KB = 0, MMU_PAGE_SIZE_4KB = 1, MMU_PAGE_SIZE_64KB = 2, MMU_PAGE_SIZE_1MB = 3
}
 MMU defines for readable setup. More...

Functions

int mmu_add_tlb_entry (long physical_addr_base, long virtual_addr_base, struct mmu_tlb_t *options)
 Adds an entry to the TLB.
int mmu_find_index_to_entry (long physical_addr, long virtual_addr, long *index)
 Search the TLB for an entry matching the given physical and virtual address and return the index.
int mmu_init (int enable, int mode, int segmentation)
 Changes mode on the MMU according to input.
int mmu_invalidate_entry (int index, int type)
 Invalidates an entry in the TLB.
int mmu_lock_entries (int entries, int type)
 Locks a specified number of entries.
void mmu_read_bear_and_tlbehi (long *bear, long *vpn)
 Reads the TLBEAR and TLBEHI registers and place the contents in bear and vpn.
int mmu_reset ()
 Resets the MMU and invalidates all TLB entries.
int mmu_search_physical_ptr (void *physical_ptr, long *virtual_addr)
 Search a physical address and get the virtual address from the TLB. The function searches the data TLBs first before searching the instruction TLBs.
int mmu_search_virtual_ptr (void *virtual_ptr, long *physical_addr)
 Search a virtual address and get the physical address from the TLB. The function searches the data TLBs first before searching the instruction TLBs.


Enumeration Type Documentation

anonymous enum

MMU defines for readable setup.

Enumerator:
MMU_ERROR 
MMU_OK 
MMU_ERROR_ARGUMENT 
MMU_TLB_MISS 
MMU_DISABLE 
MMU_ENABLE 
MMU_PRIVATE_VIRTUAL_MODE 
MMU_SHARED_VIRTUAL_MODE 
MMU_SEGMENTATION_OFF 
MMU_SEGMENTATION_ON 
MMU_TLB_TYPE_DATA 
MMU_TLB_TYPE_INSTRUCTION 
MMU_PAGE_SIZE_1KB 
MMU_PAGE_SIZE_4KB 
MMU_PAGE_SIZE_64KB 
MMU_PAGE_SIZE_1MB 

Definition at line 113 of file mmu.h.

00113      {
00114     MMU_ERROR = -1,
00115     MMU_OK = 0,
00116     MMU_ERROR_ARGUMENT = 1,
00117     MMU_TLB_MISS = 2,
00118 
00119     MMU_DISABLE = 0,
00120     MMU_ENABLE = 1,
00121     MMU_PRIVATE_VIRTUAL_MODE = 0,
00122     MMU_SHARED_VIRTUAL_MODE = 1,
00123     MMU_SEGMENTATION_OFF = 0,
00124     MMU_SEGMENTATION_ON = 1,
00125     MMU_TLB_TYPE_DATA = 0,
00126     MMU_TLB_TYPE_INSTRUCTION = 1,
00127 
00128     MMU_PAGE_SIZE_1KB = 0,
00129     MMU_PAGE_SIZE_4KB = 1,
00130     MMU_PAGE_SIZE_64KB = 2,
00131     MMU_PAGE_SIZE_1MB = 3,
00132 };


Function Documentation

int mmu_add_tlb_entry ( long  physical_addr_base,
long  virtual_addr_base,
struct mmu_tlb_t options 
)

Adds an entry to the TLB.

Parameters:
physical_addr_base base address of the physical placement
virtual_addr_base base address of the virtual placement
options options to the entry
Returns:
Status
Return values:
MMU_OK on success
MMU_ERROR_ARGUMENT on invalid arguments

Definition at line 304 of file mmu.c.

References mmu_tlb_t::access, mmu_tlb_t::asid, mmu_tlb_t::bufferable, mmu_tlb_t::cachable, mmu_tlb_t::dirty, mmu_tlb_t::global, mmu_add_entry(), MMU_DISABLE, MMU_ENABLE, MMU_ERROR_ARGUMENT, MMU_OK, MMU_PAGE_SIZE_1KB, MMU_PAGE_SIZE_1MB, MMU_PAGE_SIZE_4KB, MMU_PAGE_SIZE_64KB, MMU_TLB_TYPE_DATA, MMU_TLB_TYPE_INSTRUCTION, mmu_tlb_t::page_size, mmu_tlb_t::position, mmu_tlb_t::type, mmu_tlb_t::valid, and mmu_tlb_t::write_through.

00306 {
00307     if (!(options->valid == MMU_ENABLE
00308             || options->valid == MMU_DISABLE)) {
00309         return MMU_ERROR_ARGUMENT;
00310     }
00311     else if (!(options->type == MMU_TLB_TYPE_INSTRUCTION
00312             || options->type == MMU_TLB_TYPE_DATA)) {
00313         return MMU_ERROR_ARGUMENT;
00314     }
00315     else if (options->asid > 0xFF
00316             || options->asid < 0) {
00317         return MMU_ERROR_ARGUMENT;
00318     }
00319     else if (!(options->cachable == MMU_ENABLE
00320             || options->cachable == MMU_DISABLE)) {
00321         return MMU_ERROR_ARGUMENT;
00322     }
00323     else if (!(options->global == MMU_ENABLE
00324             || options->global == MMU_DISABLE)) {
00325         return MMU_ERROR_ARGUMENT;
00326     }
00327     else if (!(options->bufferable == MMU_ENABLE
00328             || options->bufferable == MMU_DISABLE)) {
00329         return MMU_ERROR_ARGUMENT;
00330     }
00331     else if (options->access > 0x0D
00332             || options->access < 0) {
00333         return MMU_ERROR_ARGUMENT;
00334     }
00335     else if (!(options->page_size == MMU_PAGE_SIZE_1KB
00336             || options->page_size == MMU_PAGE_SIZE_4KB
00337             || options->page_size == MMU_PAGE_SIZE_64KB
00338             || options->page_size == MMU_PAGE_SIZE_1MB)) {
00339         return MMU_ERROR_ARGUMENT;
00340     }
00341     else if (!(options->dirty == MMU_ENABLE
00342             || options->dirty == MMU_DISABLE)) {
00343         return MMU_ERROR_ARGUMENT;
00344     }
00345     else if (!(options->write_through == MMU_ENABLE
00346             || options->write_through == MMU_DISABLE)) {
00347         return MMU_ERROR_ARGUMENT;
00348     }
00349     else if (options->position < 0 ||
00350             ((options->type == MMU_TLB_TYPE_DATA &&
00351               options->position >= MMU_DTLB_ENTRIES) ||
00352              (options->type == MMU_TLB_TYPE_INSTRUCTION &&
00353               options->position >= MMU_ITLB_ENTRIES))) {
00354         return MMU_ERROR_ARGUMENT;
00355     }
00356 
00357     unsigned long vpn;
00358     unsigned long pfn;
00359     unsigned long addr_mask;
00360 
00361     if (options->page_size == MMU_PAGE_SIZE_1KB) {
00362         addr_mask = 0xFFFFFC00;
00363     }
00364     else if (options->page_size == MMU_PAGE_SIZE_4KB) {
00365         addr_mask = 0xFFFFF000;
00366     }
00367     else if (options->page_size == MMU_PAGE_SIZE_64KB) {
00368         addr_mask = 0xFFFF0000;
00369     }
00370     else if (options->page_size == MMU_PAGE_SIZE_1MB) {
00371         addr_mask = 0xFFF00000;
00372     } else {
00373         return MMU_ERROR_ARGUMENT;
00374     }
00375 
00376     vpn =
00377         (virtual_addr_base & addr_mask)|
00378         (options->valid<<AVR32_TLBEHI_V_OFFSET)|
00379         (options->type<<AVR32_TLBEHI_I_OFFSET)|
00380         (options->asid<<AVR32_TLBEHI_ASID_OFFSET);
00381 
00382     pfn =
00383         (physical_addr_base & addr_mask)|
00384         (options->cachable<<AVR32_TLBELO_C_OFFSET)|
00385         (options->global<<AVR32_TLBELO_G_OFFSET)|
00386         (options->bufferable<<AVR32_TLBELO_B_OFFSET)|
00387         (options->access<<AVR32_TLBELO_AP_OFFSET)|
00388         (options->page_size<<AVR32_TLBELO_SZ_OFFSET)|
00389         (options->dirty<<AVR32_TLBELO_D_OFFSET)|
00390         (options->write_through<<AVR32_TLBELO_W_OFFSET);
00391 
00392     int retVal = MMU_OK;
00393 
00394     retVal = mmu_add_entry(vpn, pfn, options->position, options->type);
00395 
00396     return retVal;
00397 }

Here is the call graph for this function:

int mmu_find_index_to_entry ( long  physical_addr,
long  virtual_addr,
long *  index 
)

Search the TLB for an entry matching the given physical and virtual address and return the index.

Parameters:
physical_addr the physical address to find
virtual_addr the virtual address to find
index the index of the entry from the search
Returns:
Status
Return values:
MMU_OK on success
MMU_TLB_MISS on TLB search miss

Definition at line 424 of file mmu.c.

References AVR32_READ_SR_REG, AVR32_SET_SR_REG, MMU_OK, and MMU_TLB_MISS.

00425 {
00426     long vpn = virtual_addr & 0xFFFFfc00;
00427     long pfn = physical_addr & 0xFFFFfc00;
00428 
00429     AVR32_SET_SR_REG(AVR32_TLBEHI, vpn);
00430     AVR32_SET_SR_REG(AVR32_TLBELO, pfn);
00431 
00432 #ifdef __GNUC__
00433     __builtin_tlbs();
00434 #elif __ICCAVR32__
00435     __search_TLB_entry();
00436 #else
00437 #error No known compiler used
00438 #endif
00439 
00440     long regValue = 0;
00441 
00442     AVR32_READ_SR_REG(AVR32_MMUCR, regValue);
00443 
00444     if ((regValue & AVR32_MMUCR_N_MASK) != 0) {
00445         return MMU_TLB_MISS;
00446     }
00447 
00448     /* Check for instruction or data TBL */
00449     if ((vpn & AVR32_TLBEHI_I_MASK) != 0) {
00450         *index = 0x3F & (regValue>>AVR32_MMUCR_IRP_OFFSET);
00451     } else {
00452         *index = 0x3F & (regValue>>AVR32_MMUCR_DRP_OFFSET);
00453     }
00454 
00455     return MMU_OK;
00456 }

int mmu_init ( int  enable,
int  mode,
int  segmentation 
)

Changes mode on the MMU according to input.

This function only changes the mode, it will not invalidate all the TLB entries. If this is needed use the mmu_reset function to reset the MMU back to default setup.

Parameters:
enable enable or disable the MMU
  • MMU_ENABLE
  • MMU_DISABLE
mode Set the MMU in private virtual mode or 1-shared virtual mode
  • MMU_PRIVATE_VIRTUAL_MODE
  • MMU_SHARED_VIRTUAL_MODE
segmentation Turns on or off segmentation
  • MMU_SEGMENTATION_ON
  • MMU_SEGMENTATION_OFF
Returns:
Status
Return values:
MMU_OK on success
MMU_ERROR if unable to initialize the MMU

Definition at line 81 of file mmu.c.

References AVR32_READ_SR_REG, AVR32_SET_SR_REG, MMU_ERROR, and MMU_OK.

00082 {
00083     long regval = 0;
00084     long regval_read = 0;
00085 
00086     AVR32_READ_SR_REG(AVR32_MMUCR, regval);
00087 
00088     regval = (enable<<AVR32_MMUCR_E_OFFSET)|
00089         (mode<<AVR32_MMUCR_M_OFFSET)|
00090         (segmentation<<AVR32_MMUCR_S_OFFSET);
00091 
00092     AVR32_SET_SR_REG(AVR32_MMUCR, regval);
00093 
00094     AVR32_READ_SR_REG(AVR32_MMUCR, regval_read);
00095 
00096     if (regval != regval_read) {
00097         return MMU_ERROR;
00098     }
00099 
00100     return MMU_OK;
00101 }

int mmu_invalidate_entry ( int  index,
int  type 
)

Invalidates an entry in the TLB.

Parameters:
index the TLB index of the entry to be invalidated
type data or instruction entries to invalidate
  • MMU_TLB_TYPE_INSTRUCTION
  • MMU_TLB_TYPE_DATA
Returns:
Status
Return values:
MMU_OK on success
MMU_ERROR_ARGUMENT on invalid argument

Definition at line 470 of file mmu.c.

References AVR32_CLEAR_SR_BIT, AVR32_READ_SR_REG, AVR32_SET_SR_REG, MMU_ERROR_ARGUMENT, MMU_OK, MMU_TLB_TYPE_DATA, and MMU_TLB_TYPE_INSTRUCTION.

00471 {
00472     if (index < 0 ||
00473             ((type == MMU_TLB_TYPE_DATA &&
00474               index >= MMU_DTLB_ENTRIES) ||
00475              (type == MMU_TLB_TYPE_INSTRUCTION &&
00476               index >= MMU_ITLB_ENTRIES))) {
00477         return MMU_ERROR_ARGUMENT;
00478     }
00479 
00480     long regValue = 0;
00481 
00482     AVR32_READ_SR_REG(AVR32_MMUCR, regValue);
00483 
00484     if (type == MMU_TLB_TYPE_INSTRUCTION) {
00485         regValue &= ~(0x3F<<AVR32_MMUCR_IRP_OFFSET);
00486         regValue |= (index<<AVR32_MMUCR_IRP_OFFSET);
00487     } else {
00488         regValue &= ~(0x3F<<AVR32_MMUCR_DRP_OFFSET);
00489         regValue |= (index<<AVR32_MMUCR_DRP_OFFSET);
00490     }
00491 
00492     AVR32_SET_SR_REG(AVR32_MMUCR, regValue);
00493 
00494 #ifdef __GNUC__
00495     __builtin_tlbr();
00496 #elif __ICCAVR32__
00497     __read_TLB_entry();
00498 #else
00499 #error No known compiler used
00500 #endif
00501 
00502     AVR32_CLEAR_SR_BIT(AVR32_TLBEHI, AVR32_TLBEHI_V_OFFSET);
00503 
00504 #ifdef __GNUC__
00505     __builtin_tlbw();
00506 #elif __ICCAVR32__
00507     __write_TLB_entry();
00508 #else
00509 #error No known compiler used
00510 #endif
00511 
00512     return MMU_OK;
00513 }

int mmu_lock_entries ( int  entries,
int  type 
)

Locks a specified number of entries.

Parameters:
entries number of entries to lock
type data or instruction entries to lock
  • MMU_TLB_TYPE_DATA
  • MMU_TLB_TYPE_INSTRUCTION

Definition at line 266 of file mmu.c.

References AVR32_READ_SR_REG, AVR32_SET_SR_REG, MMU_ERROR_ARGUMENT, MMU_OK, MMU_TLB_TYPE_DATA, and MMU_TLB_TYPE_INSTRUCTION.

00267 {
00268     if (entries < 0 ||
00269             ((type == MMU_TLB_TYPE_DATA &&
00270               entries >= MMU_DTLB_ENTRIES) ||
00271              (type == MMU_TLB_TYPE_INSTRUCTION &&
00272               entries >= MMU_ITLB_ENTRIES))) {
00273         return MMU_ERROR_ARGUMENT;
00274     }
00275 
00276     long regValue = 0;
00277 
00278     AVR32_READ_SR_REG(AVR32_MMUCR, regValue);
00279 
00280     if (type == MMU_TLB_TYPE_INSTRUCTION) {
00281         regValue &= ~(AVR32_MMUCR_ILA_MASK);
00282         regValue |= (entries<<AVR32_MMUCR_ILA_OFFSET);
00283     } else {
00284         regValue &= ~(AVR32_MMUCR_DLA_MASK);
00285         regValue |= (entries<<AVR32_MMUCR_DLA_OFFSET);
00286     }
00287 
00288     AVR32_SET_SR_REG(AVR32_MMUCR, regValue);
00289 
00290     return MMU_OK;
00291 }

void mmu_read_bear_and_tlbehi ( long *  bear,
long *  vpn 
)

Reads the TLBEAR and TLBEHI registers and place the contents in bear and vpn.

Parameters:
bear pointer to where to put the TLBEAR data
vpn pointer to where to put the TLBEHI data

Definition at line 406 of file mmu.c.

References AVR32_READ_SR_REG.

00407 {
00408     AVR32_READ_SR_REG(AVR32_TLBEAR, *bear);
00409     AVR32_READ_SR_REG(AVR32_TLBEHI, *vpn);
00410 }

int mmu_reset (  ) 

Resets the MMU and invalidates all TLB entries.

Returns:
Status
Return values:
MMU_OK on success
MMU_ERROR if unable to reset the MMU

Definition at line 110 of file mmu.c.

References AVR32_READ_SR_REG, AVR32_SET_SR_REG, MMU_ERROR, and MMU_OK.

00111 {
00112     long regval;
00113     int timer = 10;
00114 
00115     AVR32_SET_SR_REG(AVR32_MMUCR, AVR32_MMUCR_S_MASK|AVR32_MMUCR_I_MASK);
00116 
00117     /* Wait for invalidation of MMU entries */
00118     do {
00119         AVR32_READ_SR_REG(AVR32_MMUCR, regval);
00120         --timer;
00121     } while ((regval & AVR32_MMUCR_I_MASK) != 0 && timer > 0);
00122 
00123     if (regval != AVR32_MMUCR_S_MASK || timer == 0) {
00124         return MMU_ERROR;
00125     }
00126 
00127     AVR32_SET_SR_REG(AVR32_TLBARHI, 0);
00128     AVR32_SET_SR_REG(AVR32_TLBARLO, 0);
00129 
00130     return MMU_OK;
00131 }

int mmu_search_physical_ptr ( void *  physical_ptr,
long *  virtual_addr 
)

Search a physical address and get the virtual address from the TLB. The function searches the data TLBs first before searching the instruction TLBs.

Parameters:
physical_ptr the physical address to search for
virtual_addr pointer to a variable the virtual address will be written
Returns:
Status
Return values:
MMU_OK on success
MMU_ERROR_ARGUMENT on invalid arguments
MMU_TLB_MISS on TLB search miss

Definition at line 210 of file mmu.c.

References mmu_get_addrmask_from_page_size(), MMU_OK, mmu_read_entry(), MMU_TLB_MISS, MMU_TLB_TYPE_DATA, and MMU_TLB_TYPE_INSTRUCTION.

00211 {
00212     long addr_mask;
00213     long vpn;
00214     long pfn;
00215     int retval;
00216     int i;
00217 
00218     for (i = 0; i < MMU_DTLB_ENTRIES; i++) {
00219         /* Read the TLB entry */
00220         retval = mmu_read_entry(&vpn, &pfn, i, MMU_TLB_TYPE_DATA);
00221         if (retval != MMU_OK) {
00222             return retval;
00223         }
00224 
00225         retval = mmu_get_addrmask_from_page_size(pfn, &addr_mask);
00226         if (retval == MMU_OK) {
00227             if (((long)physical_ptr & addr_mask) == (pfn & addr_mask)
00228                     && (vpn & AVR32_TLBEHI_V_MASK)) {
00229                 *virtual_addr = (vpn & addr_mask)
00230                     |((long)physical_ptr & ~addr_mask);
00231                 return MMU_OK;
00232             }
00233         }
00234     }
00235 
00236     for (i = 0; i < MMU_ITLB_ENTRIES; i++) {
00237         /* Read the TLB entry */
00238         retval = mmu_read_entry(&vpn, &pfn, i, MMU_TLB_TYPE_INSTRUCTION);
00239         if (retval != MMU_OK) {
00240             return retval;
00241         }
00242 
00243         retval = mmu_get_addrmask_from_page_size(pfn, &addr_mask);
00244         if (retval == MMU_OK) {
00245             if (((long)physical_ptr & addr_mask) == (pfn & addr_mask)
00246                     && (vpn & AVR32_TLBEHI_V_MASK)) {
00247                 *virtual_addr = (vpn & addr_mask)
00248                     |((long)physical_ptr & ~addr_mask);
00249                 return MMU_OK;
00250             }
00251         }
00252     }
00253 
00254 
00255     return MMU_TLB_MISS;
00256 }

Here is the call graph for this function:

int mmu_search_virtual_ptr ( void *  virtual_ptr,
long *  physical_addr 
)

Search a virtual address and get the physical address from the TLB. The function searches the data TLBs first before searching the instruction TLBs.

Parameters:
virtual_ptr the virtual address to search for
physical_addr pointer to a variable the physical address will be written
Returns:
Status
Return values:
MMU_OK on success
MMU_ERROR_ARGUMENT on invalid arguments
MMU_TLB_MISS on TLB search miss

Definition at line 147 of file mmu.c.

References mmu_get_addrmask_from_page_size(), MMU_OK, mmu_read_entry(), MMU_TLB_MISS, MMU_TLB_TYPE_DATA, and MMU_TLB_TYPE_INSTRUCTION.

00148 {
00149     long addr_mask;
00150     long vpn;
00151     long pfn;
00152     int retval;
00153     int i;
00154 
00155     for (i = 0; i < MMU_DTLB_ENTRIES; i++) {
00156         /* Read the TLB entry */
00157         retval = mmu_read_entry(&vpn, &pfn, i, MMU_TLB_TYPE_DATA);
00158         if (retval != MMU_OK) {
00159             return retval;
00160         }
00161 
00162         retval = mmu_get_addrmask_from_page_size(pfn, &addr_mask);
00163         if (retval == MMU_OK) {
00164             if (((long)virtual_ptr & addr_mask) == (vpn & addr_mask)
00165                     && (vpn & AVR32_TLBEHI_V_MASK)) {
00166                 *physical_addr = (pfn & addr_mask)
00167                     |((long)virtual_ptr & ~addr_mask);
00168                 return MMU_OK;
00169             }
00170         }
00171     }
00172 
00173     for (i = 0; i < MMU_ITLB_ENTRIES; i++) {
00174         /* Read the TLB entry */
00175         retval = mmu_read_entry(&vpn, &pfn, i, MMU_TLB_TYPE_INSTRUCTION);
00176         if (retval != MMU_OK) {
00177             return retval;
00178         }
00179 
00180         retval = mmu_get_addrmask_from_page_size(pfn, &addr_mask);
00181         if (retval == MMU_OK) {
00182             if (((long)virtual_ptr & addr_mask) == (vpn & addr_mask)
00183                     && (vpn & AVR32_TLBEHI_V_MASK)) {
00184                 *physical_addr = (pfn & addr_mask)
00185                     |((long)virtual_ptr & ~addr_mask);
00186                 return MMU_OK;
00187             }
00188         }
00189     }
00190 
00191 
00192 
00193     return MMU_TLB_MISS;
00194 }

Here is the call graph for this function:


Generated on Thu Oct 18 09:30:02 2007 for AVR32113 Configuration and Use of the Memory Management Unit by  doxygen 1.5.3