mmu_example.c

Go to the documentation of this file.
00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
00023 /* Copyright (c) 2006, Atmel Corporation All rights reserved.
00024  *
00025  * Redistribution and use in source and binary forms, with or without
00026  * modification, are permitted provided that the following conditions are met:
00027  *
00028  * 1. Redistributions of source code must retain the above copyright notice,
00029  * this list of conditions and the following disclaimer.
00030  *
00031  * 2. Redistributions in binary form must reproduce the above copyright notice,
00032  * this list of conditions and the following disclaimer in the documentation
00033  * and/or other materials provided with the distribution.
00034  *
00035  * 3. The name of ATMEL may not be used to endorse or promote products derived
00036  * from this software without specific prior written permission.
00037  *
00038  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
00039  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00040  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
00041  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00042  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00043  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00044  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00045  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00046  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00047  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00048  */
00049 
00050 #include <avr32/io.h>
00051 #include <string.h>
00052 #include <malloc.h>
00053 #include <sys/exceptions.h>
00054 #include "settings.h"
00055 #include "macro.h"
00056 #include "usart.h"
00057 #include "mmu.h"
00058 
00060 static int free_page_nr = 16;
00062 static volatile avr32_pio_t *pioa = &AVR32_PIOA;
00064 static volatile avr32_pio_t *piob = &AVR32_PIOB;
00066 static volatile avr32_pio_t *pioc = &AVR32_PIOC;
00068 static volatile avr32_usart_t *usart = &USART_MODULE;
00070 static unsigned long handler_table[0x104];
00071 
00078 unsigned int mmu_exception(int evba_offset, int return_address)
00079 {
00080     int retval;
00081     long bear;
00082     long vpn;
00083     long pfn;
00084     struct mmu_tlb_t tlbOptions;
00085     tlbOptions.valid = MMU_ENABLE;
00086     tlbOptions.type = MMU_TLB_TYPE_DATA;
00087     tlbOptions.asid = 0;
00088     tlbOptions.cachable = MMU_DISABLE;
00089     tlbOptions.global = MMU_DISABLE;
00090     tlbOptions.bufferable = MMU_DISABLE;
00091     tlbOptions.access = 0x03; /* read/write/execute */
00092     tlbOptions.page_size = MMU_PAGE_SIZE_64KB;
00093     tlbOptions.dirty = MMU_ENABLE;
00094     tlbOptions.write_through = MMU_DISABLE;
00095     tlbOptions.position = -1;
00096 
00097     printf("\r\n* Handling exception: ");
00098 
00099     switch (evba_offset) {
00100     case EVBA_ITLB_MISS:
00101     case EVBA_DTLB_MISS_W:
00102     case EVBA_DTLB_MISS_R:
00103         mmu_read_bear_and_tlbehi(&bear, &vpn);
00104         printf("TLB miss at virtual address 0x%08lx\r\n", bear);
00105         printf("  Bear is 0x%08lx\r\n", bear);
00106         printf("  Vpn  is 0x%08lx\r\n", vpn);
00107 
00108         /* Add the page to TLB */
00109         if (free_page_nr > MMU_DTLB_ENTRIES) {
00110             free_page_nr = 16;
00111         }
00112         tlbOptions.position = free_page_nr++;
00113         printf("  Adding page to TLB[%02d]...  ", tlbOptions.position);
00114         /* in SRAM segment */
00115         if (((bear ^ 0x24000000) >> 24) == 0) {
00116             pfn = 0x24000000;
00117         } else {
00118             pfn = 0;
00119         }
00120         retval = mmu_add_tlb_entry(pfn, bear, &tlbOptions);
00121         if (retval != MMU_OK) {
00122             printf("[ FAILED ]\r\n");
00123             goto out;
00124         }
00125         printf("[ OK ]\r\n");
00126         break;
00127     default:
00128         printf("unhandled exception 0x%08x!\r\n", evba_offset);
00129     }
00130 
00131 out:
00132     printf("\n");
00133     return return_address;
00134 }
00135 
00136 
00142 int mmuex_exceptions()
00143 {
00144     int retval = MMU_OK;
00145     char * string_p = "this test string is used to generate exceptions";
00146     char * string_p61 = (char *)((long) string_p | 0x61800000);
00147 
00148     printf("\r\nDemonstrate MMU mode...\r\n");
00149     printf("  Segmentation: ON\r\n");
00150     printf("  Paging      : ON\r\n");
00151     printf("  Exceptions  : ON\r\n\n");
00152 
00153     /* Reset MMU */
00154     printf("  Reset MMU...               ");
00155     retval = mmu_reset();
00156     if (retval != MMU_OK) {
00157         printf("[ FAILED ]\r\n");
00158         goto error;
00159     }
00160     printf("[ OK ]\r\n");
00161 
00162     /* Set shared mode */
00163     printf("  Set MMU in shared mode...  ");
00164     retval = mmu_init(MMU_DISABLE,
00165             MMU_SHARED_VIRTUAL_MODE,
00166             MMU_SEGMENTATION_ON);
00167     if (retval != MMU_OK) {
00168         printf("[ FAILED ]\r\n");
00169         goto error;
00170     }
00171     printf("[ OK ]\r\n");
00172 
00173     struct mmu_tlb_t tlbOptions;
00174     tlbOptions.valid = MMU_ENABLE;
00175     tlbOptions.type = MMU_TLB_TYPE_DATA;
00176     tlbOptions.asid = 0;
00177     tlbOptions.cachable = MMU_DISABLE;
00178     tlbOptions.global = MMU_DISABLE;
00179     tlbOptions.bufferable = MMU_DISABLE;
00180     tlbOptions.access = 0x03; /* read/write/execute */
00181     tlbOptions.page_size = MMU_PAGE_SIZE_64KB;
00182     tlbOptions.dirty = MMU_ENABLE;
00183     tlbOptions.write_through = MMU_DISABLE;
00184     tlbOptions.position = -1;
00185 
00186     /* Add the segments to TLB */
00187 
00188     /* Inset NOR flash at address 0 */
00189     printf("  Adding segments to TLB...  ");
00190     tlbOptions.position = 12;
00191     retval = mmu_add_tlb_entry(0, 0, &tlbOptions);
00192     if (retval != MMU_OK) {
00193         printf("[ FAILED ]\r\n");
00194         goto error;
00195     }
00196     /* Insert the internal SRAM */
00197     tlbOptions.position = 14;
00198     retval = mmu_add_tlb_entry(0x24000000, 0x24000000, &tlbOptions);
00199     if (retval != MMU_OK) {
00200         printf("[ FAILED ]\r\n");
00201         goto error;
00202     }
00203     printf("[ OK ]\r\n");
00204 
00205     /* Change mode */
00206     printf("  Changing mode...           ");
00207     retval = mmu_init(MMU_ENABLE,
00208             MMU_SHARED_VIRTUAL_MODE,
00209             MMU_SEGMENTATION_ON);
00210     if (retval != MMU_OK) {
00211         printf("[ FAILED ]\r\n");
00212         goto error;
00213     }
00214     printf("[ OK ]\r\n");
00215 
00216     printf("\r\n");
00217     printf("  String   (0x%08lx): %s\r\n", (long)string_p, string_p);
00218     /* Use the pointer in the 0x6180xxxx segment without adding the page.
00219      * This will generate an exception */
00220     strcpy(string_p61, string_p);
00221 
00222     /* Print out the string which should now be available */
00223     printf("  String61 (0x%08lx): %s\r\n", (long)string_p61, string_p61);
00224 
00225     printf("\r\n");
00226     printf("  Test result...             ");
00227 
00228     if (strcmp(string_p, string_p61) == 0) {
00229         printf("[ OK ]\r\n\n");
00230     } else {
00231         printf("[ FAILED ]\r\n\n");
00232     }
00233 
00234     return retval;
00235 error:
00236     printf("\r\n");
00237     printf("  Test result... (jumped)    [ FAILED ]\r\n\n");
00238     return retval;
00239 }
00240 
00241 
00247 int mmuex_segon_pageon()
00248 {
00249     int retval = MMU_OK;
00250     char * string_p = "MMU test segmentation on, paging on";
00251     long string_p64 = (long) string_p | 0x64080000;
00252     long string_pPA = 0;
00253     long string_pVA = 0;
00254 
00255     printf("\r\nDemonstrate MMU mode...\r\n");
00256     printf("  Segmentation: ON\r\n");
00257     printf("  Paging      : ON\r\n\n");
00258 
00259     /* Reset MMU */
00260     printf("  Reset MMU...               ");
00261     retval = mmu_reset();
00262     if (retval != MMU_OK) {
00263         printf("[ FAILED ]\r\n");
00264         goto error;
00265     }
00266     printf("[ OK ]\r\n");
00267 
00268     /* Set shared mode */
00269     printf("  Set MMU in shared mode...  ");
00270     retval = mmu_init(MMU_DISABLE,
00271             MMU_SHARED_VIRTUAL_MODE,
00272             MMU_SEGMENTATION_ON);
00273     if (retval != MMU_OK) {
00274         printf("[ FAILED ]\r\n");
00275         goto error;
00276     }
00277     printf("[ OK ]\r\n");
00278 
00279     struct mmu_tlb_t tlbOptions;
00280     tlbOptions.valid = MMU_ENABLE;
00281     tlbOptions.type = MMU_TLB_TYPE_DATA;
00282     tlbOptions.asid = 0;
00283     tlbOptions.cachable = MMU_DISABLE;
00284     tlbOptions.global = MMU_DISABLE;
00285     tlbOptions.bufferable = MMU_DISABLE;
00286     tlbOptions.access = 0x03; /* read/write/execute */
00287     tlbOptions.page_size = MMU_PAGE_SIZE_64KB;
00288     tlbOptions.dirty = MMU_ENABLE;
00289     tlbOptions.write_through = MMU_DISABLE;
00290     tlbOptions.position = -1;
00291 
00292     /* Add the segments to TLB */
00293     printf("  Adding segments to TLB...  ");
00294     tlbOptions.position = 12;
00295     retval = mmu_add_tlb_entry(0, 0, &tlbOptions);
00296     if (retval != MMU_OK) {
00297         printf("[ FAILED ]\r\n");
00298         goto error;
00299     }
00300     tlbOptions.position = 14;
00301     retval = mmu_add_tlb_entry(0x24000000, 0x24000000, &tlbOptions);
00302     if (retval != MMU_OK) {
00303         printf("[ FAILED ]\r\n");
00304         goto error;
00305     }
00306 
00307     /* Add a memory address which maps to string_p */
00308     tlbOptions.position = 11;
00309     retval = mmu_add_tlb_entry((long)string_p, 0x64080000, &tlbOptions);
00310     if (retval != MMU_OK) {
00311         printf("[ FAILED ]\r\n");
00312         goto error;
00313     }
00314     printf("[ OK ]\r\n");
00315 
00316     /* Change mode */
00317     printf("  Changing mode...           ");
00318     retval = mmu_init(MMU_ENABLE,
00319             MMU_SHARED_VIRTUAL_MODE,
00320             MMU_SEGMENTATION_ON);
00321     if (retval != MMU_OK) {
00322         printf("[ FAILED ]\r\n");
00323         goto error;
00324     }
00325     printf("[ OK ]\r\n");
00326 
00327     /* Search and get the physical
00328      * address to the pointer
00329      */
00330     printf("  Lookup physical address... ");
00331     retval = mmu_search_virtual_ptr((void *)string_p64, &string_pPA);
00332     if (retval != MMU_OK) {
00333         printf("[ FAILED ]\r\n");
00334         goto error;
00335     }
00336     printf("[ OK ]\r\n");
00337 
00338     /* Search and get the virtual
00339      * address to the pointer
00340      */
00341     printf("  Lookup virtual address...  ");
00342     retval = mmu_search_physical_ptr((void *)string_pPA, &string_pVA);
00343     if (retval != MMU_OK) {
00344         printf("[ FAILED ]\r\n");
00345         goto error;
00346     }
00347     printf("[ OK ]\r\n");
00348 
00349     /* Find the index for the TLB entry */
00350     long tlbIndex;
00351     printf("  Get TLB index... ");
00352     retval = mmu_find_index_to_entry(string_pPA, string_pVA, &tlbIndex);
00353     if (retval != MMU_OK) {
00354         printf("          [ FAILED ]\r\n");
00355         goto error;
00356     }
00357     printf("[%02ld]      [ OK ]\r\n", tlbIndex);
00358 
00359     printf("\r\n");
00360     printf("  String   (0x%08lx): %s\r\n", (long)string_p, string_p);
00361     printf("  String64 (0x%08lx): %s\r\n", (long)string_p64, (char *)string_p64);
00362     printf("  StringPA (0x%08lx): %s\r\n", (long)string_pPA, (char *)string_pPA);
00363     printf("  StringVA (0x%08lx): %s\r\n", (long)string_pVA, (char *)string_pVA);
00364     printf("\r\n");
00365     printf("  Test result...             ");
00366 
00367     if (strcmp(string_p, (char *)string_pPA) == 0 &&
00368             strcmp(string_p, (char *)string_pVA) == 0) {
00369         printf("[ OK ]\r\n\n");
00370     } else {
00371         printf("[ FAILED ]\r\n\n");
00372     }
00373 
00374     return retval;
00375 error:
00376     printf("\r\n");
00377     printf("  Test result... (jumped)    [ FAILED ]\r\n\n");
00378     return retval;
00379 }
00380 
00381 
00387 int mmuex_segon_pageoff()
00388 {
00389     int retval = MMU_OK;
00390     char * string_p80 = 0;
00391     char * string_pA0 = 0;
00392     char * string_pC0 = 0;
00393     char * string_p = "MMU test segmentation off, paging on";
00394 
00395     printf("\r\nDemonstrate MMU mode...\r\n");
00396     printf("  Segmentation: ON\r\n");
00397     printf("  Paging      : OFF\r\n\n");
00398 
00399     /* Reset MMU */
00400     printf("  Reset MMU...               ");
00401     retval = mmu_reset();
00402     if (retval != MMU_OK) {
00403         printf("[ FAILED ]\r\n");
00404         goto error;
00405     }
00406     printf("[ OK ]\r\n");
00407 
00408     /* Change mode */
00409     printf("  Changing mode...           ");
00410     retval = mmu_init(MMU_DISABLE,
00411             MMU_SHARED_VIRTUAL_MODE,
00412             MMU_SEGMENTATION_ON);
00413     if (retval != MMU_OK) {
00414         printf("[ FAILED ]\r\n");
00415         goto error;
00416     }
00417     printf("[ OK ]\r\n");
00418 
00419     string_p80 = (void*)(0x80000000|(long)string_p);
00420     string_pA0 = (void*)(0xA0000000|(long)string_p);
00421     string_pC0 = (void*)(0xC0000000|(long)string_p);
00422 
00423     printf("\r\n");
00424     printf("  String   (%08x): %s\r\n", (int)string_p, string_p);
00425     printf("  String80 (%08x): %s\r\n", (int)string_p80, string_p80);
00426     printf("  StringA0 (%08x): %s\r\n", (int)string_pA0, string_pA0);
00427     printf("  StringC0 (%08x): %s\r\n", (int)string_pC0, string_pC0);
00428     printf("\r\n");
00429     printf("  Test result...             ");
00430 
00431     if (strcmp(string_p, string_p80) == 0 &&
00432             strcmp(string_p, string_pA0) == 0 &&
00433             strcmp(string_p, string_pC0) == 0) {
00434         printf("[ OK ]\r\n\n");
00435     } else {
00436         printf("[ FAILED ]\r\n\n");
00437     }
00438 
00439     return retval;
00440 error:
00441     printf("\r\n");
00442     printf("  Test result... (jumped)    [ FAILED ]\r\n\n");
00443     return retval;
00444 }
00445 
00449 extern char _evba[];
00450 
00456 int main(int argc, char * argv[])
00457 {
00458     int error = 0;
00459 
00460     /* set up exceptions */
00461     init_exceptions((void *)_evba, handler_table);
00462     _register_exception_handler(&mmu_exception, EVBA_ITLB_MISS);
00463     _register_exception_handler(&mmu_exception, EVBA_DTLB_MISS_R);
00464     _register_exception_handler(&mmu_exception, EVBA_DTLB_MISS_W);
00465     _register_exception_handler(&mmu_exception, EVBA_DTLB_MODIFIED);
00466 
00467     /* disable all interrupts on PIO */
00468     pioa->idr = 0xFFFFffff;
00469     piob->idr = 0xFFFFffff;
00470     pioc->idr = 0xFFFFffff;
00471 
00472     /* Enable USART on PIOA */
00473     pioa->pdr = AVR32_PIO_P17_MASK|AVR32_PIO_P18_MASK;
00474     pioa->asr = AVR32_PIO_P17_MASK|AVR32_PIO_P18_MASK;
00475 
00476     /* Enable PIO as debug output/input
00477      * Output: PC0 => PC15
00478      * Input : PB0 => PB7
00479      */
00480     piob->per = 0x000000FF;
00481     piob->odr = 0x000000FF;
00482     piob->ifer = 0x000000FF;
00483     piob->odsr = 0x00000000;
00484     piob->puer = 0x000000FF;
00485 
00486     pioc->per = 0x0000FFFF;
00487     pioc->oer = 0x0000FFFF;
00488     pioc->ower = 0x0000FFFF;
00489     pioc->odsr = 0x00000000;
00490 
00491     /* Set options for the USART */
00492     struct usart_options_t usartOptions;
00493     usartOptions.baudrate = USART_BAUD;
00494     usartOptions.charlength = USART_BITS;
00495     usartOptions.paritytype = USART_NO_PARITY;
00496     usartOptions.stopbits = USART_1_STOPBIT;
00497     usartOptions.channelmode = USART_NORMAL_CHMODE;
00498 
00499     /* Initialize USART in RS232 mode */
00500     error = usart_linit(usart, &usartOptions, CPUHZ);
00501 
00502     if (error != USART_OK) {
00503         pioc->odsr = AVR32_PIO_P8_MASK|AVR32_PIO_P9_MASK;
00504         for (;;);
00505     }
00506 
00507     printf("AVR32113: available demos:\r\n");
00508     printf("  SW2 - segmentation on\r\n");
00509     printf("        paging       on\r\n");
00510     printf("        exception example\r\n\n");
00511     printf("  SW1 - segmentation on\r\n");
00512     printf("        paging       on\r\n\n");
00513     printf("  SW0 - segmentation on\r\n");
00514     printf("        paging       off\r\n\n");
00515 
00516     unsigned int buttontimer = 0;
00517 
00518     for (;;) {
00519         /* SW2 - Page miss example
00520          * SW1 - Segment translation on, page translation on
00521          * SW0 - Segment translation on, page translation off (default)
00522          */
00523         if ((piob->pdsr & AVR32_PIO_P2_MASK) == 0 &&
00524                 buttontimer == 0) {
00525             pioc->odsr = AVR32_PIO_P2_MASK;
00526             buttontimer = DELAY_TIMEOUT;
00527 
00528             int retval = MMU_OK;
00529 
00530             retval = mmuex_exceptions();
00531 
00532             if (retval == MMU_OK) {
00533                 pioc->odsr = AVR32_PIO_P10_MASK|AVR32_PIO_P11_MASK;
00534             } else {
00535                 pioc->odsr = AVR32_PIO_P8_MASK|AVR32_PIO_P9_MASK;
00536             }
00537         }
00538         else if ((piob->pdsr & AVR32_PIO_P1_MASK) == 0 &&
00539                 buttontimer == 0) {
00540             pioc->odsr = AVR32_PIO_P1_MASK;
00541             buttontimer = DELAY_TIMEOUT;
00542 
00543             int retval = MMU_OK;
00544 
00545             retval = mmuex_segon_pageon();
00546 
00547             if (retval == MMU_OK) {
00548                 pioc->odsr = AVR32_PIO_P10_MASK|AVR32_PIO_P11_MASK;
00549             } else {
00550                 pioc->odsr = AVR32_PIO_P8_MASK|AVR32_PIO_P9_MASK;
00551             }
00552         }
00553         else if ((piob->pdsr & AVR32_PIO_P0_MASK) == 0 &&
00554                 buttontimer == 0) {
00555             pioc->odsr = AVR32_PIO_P0_MASK;
00556             buttontimer = DELAY_TIMEOUT;
00557 
00558             int retval = MMU_OK;
00559 
00560             retval = mmuex_segon_pageoff();
00561 
00562             if (retval == MMU_OK) {
00563                 pioc->odsr = AVR32_PIO_P10_MASK|AVR32_PIO_P11_MASK;
00564             } else {
00565                 pioc->odsr = AVR32_PIO_P8_MASK|AVR32_PIO_P9_MASK;
00566             }
00567         }
00568 
00569         if (buttontimer > 0) {
00570             --buttontimer;
00571         }
00572     }
00573 
00574     return 0;
00575 }
00576 

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