реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> ep9307. Вирутальные адреса. Переадресация RAM ROM, Как выполнить инструкцию после переопределения адресов(с помощью MMU)
Микула
сообщение Dec 17 2013, 06:44
Сообщение #1





Группа: Участник
Сообщений: 12
Регистрация: 4-12-13
Пользователь №: 79 488



Есть программа, которая выполняет настройку виртуальных адресов с помощью MMU.
RAM располагается на физических адресах 0x30..0 а ROM на адресах 0x0..0.
Появилась необходимость переадресовать RAM по нулевым адресам (0x0..0).
Собственно, для этого нужно переадресовать весь RAM и ROM, но в данный момент по этим адресам выполняется текущая программа..
После включения MMU программа сразу улетит в тар_тара-ры?
Как мне после включения MMU вызвать другую программу по определенному адресу (установить PC)?
Использую IAR4.
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение Dec 17 2013, 10:24
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



По-моему, либо выполнять настройку MMU и переход из тех адресов, для которых физический адрес = виртуальному адресу, либо обеспечить синхронность кусочков кода по физическому адресу 1 и физическому адресу 2 (виртуальный адрес которого после включения MMU будет равен физическому адресу 1), либо выполнить переход командой mov pc, rX, которая непосредственно следует за командой, обеспечивающей включение MMU, и этот mov в момент выполнения переключения уже будет выбран в конвеер и выполнится своим чередом.
Go to the top of the page
 
+Quote Post
Микула
сообщение Dec 18 2013, 12:25
Сообщение #3





Группа: Участник
Сообщений: 12
Регистрация: 4-12-13
Пользователь №: 79 488



При выполнении инструкции asm("mov pc, #0x0; "); вываливается в abort data.
После настойки ММУ настраиваю только домен (все разрешено) и табличку с ссылкой на неё.
Все кеши отрублены.
По нулевым адресам ( RAM после настройки ММУ) лежит программа которая должна запуститься..
Если выставляю в отладчике принудительно PC 0 то программа нужная работает как часы.


Привожу код настройки ММУ и перехода. Извиняюсь за коменты на русском:

Код
#include "MMU.h"
#include <intrinsics.h>
#define MB_SIZE 0x100000
#define KB_SIZE 0x400
  
#define START_RAM_ADR 0x30000000              //àäðåñ RAM ôèçè÷åñêèé
#define START_ROM_ADR 0x0                     //àäðåñ ROM ôèçè÷åñêèé

#define TBL_SIZE 16*KB_SIZE //16êá
#define TBL_ADR START_RAM_ADR+MB_SIZE-TBL_SIZE //àäðåñ áàçîâîé òàáëèöû â êîíöå RAM
#define TBL_PAGE_SIZE 4*KB_SIZE  
#define TBL_PAGE_ADR TBL_ADR - TBL_PAGE_SIZE

//---PAGE TYPE
#define TYPE_DESCR_COARCE_PAGE 1
#define TYPE_DESCR_SECTOR 2
#define TYPE_DESCR_FINE_PAGE 3
//-------------

#define GET_DOMAIN(NUM) NUM<<5

#define GET_SECT_TABLE_DESC(ADRESS) ( (ADRESS>>20) & 0xFFF)<<20
#define GET_1KB_PAGE_DESC(ADRESS) ( (ADRESS>>10) & 0x3FFFFF)<<10

#define GET_FPAGE_TABLE_ADR(ADRESS) ( (ADRESS>>12) & 0xFFFFF) <<12

#define TYPE_1KB_PAGE   3
#define TYPE_4KB_PAGE   2
#define TYPE_64KB_PAGE  1

#define AP_R_W 3


#define CACH_MODE_WB   3<<2
#define CACH_MODE_WT   2<<2
#define CACH_MODE_NCB  1<<2
#define CACH_MODE_NCNB 0<<2

//---MMU Control
#define ENABLE_MMU 1

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

void _write_TTB(unsigned int ttb)
{
    __MCR(15, 0, ttb, 2, 0, 0);
}
//----------------------------------------------------------------------------

void _write_domain(unsigned int domain)
{
    __MCR(15, 0, domain, 3, 0, 0);
}
//----------------------------------------------------------------------------

unsigned int _read_MMU_control()
{
    register unsigned int ctl;
    ctl = __MRC(15, 0, 1, 0, 0);
        return ctl;
}
//----------------------------------------------------------------------------

void _write_MMU_control(unsigned int ctl)
{
     __MCR(15, 0, ctl, 1, 0, 0);
}
//----------------------------------------------------------------------------
int MMU_init()
{
    unsigned int ctl = _read_MMU_control();
    if(ctl & ENABLE_MMU)
        asm("mov pc, #0x0;");
    
    unsigned int   *TLB  =(unsigned int *) (TBL_ADR);
    unsigned int   *TLB_PAGE  =(unsigned int *) (TBL_PAGE_ADR);
    
    _write_domain(0xFFFFFFFF); // Ïðàâà äîñòóïà íå ïðîâåðÿþòñÿ äëÿ âñåõ äîìåíîâ
    _write_TTB(TBL_ADR);//çàïèñûâàåì àäðåñ áàçîâîé òàáëèöû
    
    
    for(int i=0;i<0x100;i++)
    {    
      TLB[0x0+i] = 0;//Îïåðàòèâíàÿ áàìÿòü áóäåò ïåðåîáîçíà÷åíà íèæå äëÿ 1 ìåãàáàéòà      
      TLB[0x100+i] = 0;    
      TLB[0x200+i] = 0;
      TLB[0x300+i] = 0;
      TLB[0x400+i] = 0;
      TLB[0x500+i] = 0;
      
      //òóò FPGA
      TLB[0x600+i] = 1<<4 | TYPE_DESCR_SECTOR | GET_DOMAIN(0) | GET_SECT_TABLE_DESC(0x60000000 +i*MB_SIZE);// | CACH_MODE_WB;
      TLB[0x700+i] = 0;
      
      //òóò ðåãèñòðû (íå êýøèðóåì)
      TLB[0x800+i] = 1<<4 | TYPE_DESCR_SECTOR | GET_DOMAIN(0) | GET_SECT_TABLE_DESC(0x80000000 + i*MB_SIZE);
      
      TLB[0x900+i] = 0;
      
      //òóò áóäåò RAM 16ìá
      TLB[0xA00+i] = 0;
      
      TLB[0xB00+i] = 0;    
      TLB[0xC00+i] = 0;
      TLB[0xE00+i] = 0;
      TLB[0xD00+i] = 0;
      TLB[0xF00+i] = 0;
    }
    
    //Íàñòðàèâàåì îïåðòèâêó 1ÌÁ-------------  
    //Äëÿ îïðåòàâíîé ïàìÿòè äåëàåì áîëåå òî÷íóþ íàñòðîéêó
    TLB[0] = 1<<4 | TYPE_DESCR_FINE_PAGE | GET_DOMAIN(0) |
          GET_FPAGE_TABLE_ADR(TBL_PAGE_ADR);  
    
    //òåïåðü íàñòðàèâàåì áîëåå òî÷íóþ òàáëèöó ïî 1êá äëÿ îïåðàòèâêè
    for(int i=0;i<1004;i++)
        TLB_PAGE[i]=TYPE_1KB_PAGE | GET_1KB_PAGE_DESC(0x30000000+i*KB_SIZE) | AP_R_W<<4;// | CACH_MODE_WB;
    
    for(int i=1004;i<1024;i++)
        TLB_PAGE[i]= 0;//äåëàåì îáðàùåíèå ïî àäðåñàì ãäå ëåæàò òàáëèöû íåäîñòóïíûìè        
    //--------------------------------------
    
    
    //Íàñòðàèâàåì ROM 16ìá------------------
    TLB[0xA00] = 1<<4 | TYPE_DESCR_FINE_PAGE | GET_DOMAIN(0) |
          GET_FPAGE_TABLE_ADR(TBL_PAGE_ADR);
    for(int i=0;i<16;i++)
    {
        TLB[0xA00+i]= 1<<4 | TYPE_DESCR_SECTOR | GET_DOMAIN(0) |
            GET_SECT_TABLE_DESC(0x0+i*MB_SIZE)|;//CACH_MODE_WB;//FLASH c 0x0 âåøàåì íà 0xA0000000        
    }  
    //--------------------------------------
    
    
    ctl = _read_MMU_control();
//
////Âêëþ÷àåì  Icash
    //ctl |= (1 << 12);
//    //Âêëþ÷àåì  Dcash  
       //ctl |= (1 << 2);    

    //ïåðåäâèãàåì PC íà íà÷àëî îïåðàòèâêè (òàì äîëæíà ðàñïîëàãàòñÿ ïðîãðàììà)
    //âêëþ÷àåì MMU*/
    ctl |= ENABLE_MMU;
    _write_MMU_control(ctl);
    //asm("mov lr, pc;                ");
    asm("mov pc, #0x0;              ");
    //---
}
Go to the top of the page
 
+Quote Post
Микула
сообщение Dec 19 2013, 07:09
Сообщение #4





Группа: Участник
Сообщений: 12
Регистрация: 4-12-13
Пользователь №: 79 488



Вываливалось в data abort на PC потому, что я забыл записать "1111" в контрольный регистр ММУ.
После включения ММУ в дебагере вижу что команды асемблеровские не исполняются и через пару действий улетают в data abort.
Сюда по всему после включения ММУ он выполняет что-то уже по перемапированным адресам...
Хотелось бы найти другой способ кроме копирования программы по новым адресам перед включениям ММУ.
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение Dec 19 2013, 08:04
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



На мой взгляд, вызов _write_MMU_control() может содержать обвязку из команд сохранения/восстановления регистров, так что (mov pc, #0x0) вполне может не влезть в конвеер sm.gif Может, стоит переписать _write_MMU_control() на ассемблере? Да, ещё неплохо бы переключить стеки, если у Вас ремаппится всё ОЗУ, необходимо скоректировать содержимое всех R13(SP) (для всех режимов работы процессора). Ну и не забыть про все указатели, содержащие актаульные адреса в ОЗУ на момент переключения sm.gif
Go to the top of the page
 
+Quote Post
Микула
сообщение Dec 19 2013, 12:04
Сообщение #6





Группа: Участник
Сообщений: 12
Регистрация: 4-12-13
Пользователь №: 79 488



Зря я сказал, что забыл записать "1111" в контрольный регистр ММУ. (не забывал).
_write_MMU_control() возврат к коду выполняется в одну ассемблер инструкцию + одна на сдвиг PC в конвейер должно померещатся (в дизасемблере по крайней мере так).
Пробовал и так и так все равно вываливается сразу сразу после MCR2 PC менял . PC просто не меняется и через несколько шагов вываливается код в аборт.
Конечно SP для каждого режима настраиваются под ремапированные адреса в стартапе программы на которую мы переходим PC.

Решил не маяться больше с этим, сделал копию программы по адресам после ремапинга.. - все заработало.
Собственно программа нормально перешла по адресу где лежит следующая программа, которую я пытался запустить. Я её соответственно сдвинул.

Кстати в примерах ИАР нашел комент, что после вклчючения ММУ следующие две инструкции должны быть NOP. Получается что он не всегда включается сразу после записи данных в контрольный регистр ММУ.

Спасибо за советы!


Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 28th August 2025 - 23:15
Рейтинг@Mail.ru


Страница сгенерированна за 0.07013 секунд с 7
ELECTRONIX ©2004-2016