📄 board_at91ev40.cpp
字号:
/*
* Copyright (c) 2005 Zhejiang University, P.R.China
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
//=============================================================================
/**
* \file Arch/ARM/Board_AT91EV40.cpp
*
* $Id: Board_AT91EV40.cpp,v 1.2 2005/06/21 02:27:06 qilj Exp $
*
* \author zhao jun <junzhao_china@yahoo.com.cn>
*/
//=============================================================================
#include "./Board_AT91EV40.h"
#include "Processor_7TDMI.h"
#include "Core/System.h"
#include "Core/Memory.h"
#include "Core/Helper.h"
#include "Core/ConfigFile.h"
#include "Device/UART/UART.h"
#include <cstdio>
#include <fstream>
#include "iostream"
namespace ARM
{
bool Board_AT91EV40::load_fs(std::string name, Core::u32 addr)
{
std::string filepath = Core::Host_Machine::gen_fullpath(Core::Host_Machine::get_image_path("ARM"), name);
std::ifstream fs((const char *)filepath.c_str(), std::ios::binary);
if (fs.fail())
{
return false;
}
Core::Bytecode_Type buffer;
char ch;
while(fs.get(ch))
{
buffer.push_back(ch);
}
CPU_7TDMI *cpu = (CPU_7TDMI *)Core::Wukong_Get_System().get_cpu();
cpu->get_mmu().access(Core::Memory_32Bit::MEMORY_WRITE, addr, buffer.size(), buffer);
return true;
}
void Board_AT91EV40::on_reset()
{
uart_ = (Core::Device<Core::u32> *) (Core::Wukong_Get_System().get_device("UART"));
WUKONG_ASSERT(uart_ != NULL);
std::string arch_name = Core::Wukong_Get_System().get_arch_name();
std::string conf_file = Core::Wukong_Get_System().get_conf_name();
Core::Wukong_Get_System().load_config(arch_name, conf_file);
Core::Config_File * cf = Core::Wukong_Get_System().get_config();
Core::u32 device_count;
cf->read("/board/device_count", device_count);
for (size_t i = 0; i < device_count;i++)
{
char path[32];
sprintf(path, "/device/%d/name", i);
std::string device_name;
cf->read(path, device_name);
if (device_name == "NIC8019")
{
//lijc add
nic8019_ = (Core::Device<Core::u32> *)(Core::Wukong_Get_System().get_device("NIC8019"));
WUKONG_ASSERT( nic8019_!=NULL);
is_nic8019_ = true;
}
else
is_nic8019_ = false;
}
cpu_ = (CPU_7TDMI *)Core::Wukong_Get_System().get_cpu();
WUKONG_ASSERT(cpu_ != NULL);
mmu_ = &((Core::MMU<Core::u32> &)cpu_->get_mmu());
WUKONG_ASSERT(mmu_ != NULL);
clock = 0xFFF;
io_prescale_ = 50;
cpu_->set_exp_priority(CPU_7TDMI::CPU_Interrupt::NO_exp);
for(size_t i=0; i<Board_AT91EV40::Signal_End; ++i)
{
signal_[i] = 0;
}
aic_reg_[AIC_ISR] = 0;
aic_reg_[AIC_IVR] = 0x1000;
aic_reg_[AIC_IMR] = 0;
is_kb_input_ = false;
//lijc add
is_nic_input_=false;
}
void Board_AT91EV40::on_destroy()
{
if(uart_ != NULL)
delete uart_;
if(nic8019_!= NULL)
delete nic8019_;
}
bool Board_AT91EV40::prepare_rom(void)
{
std::string arch_name = Core::Wukong_Get_System().get_arch_name();
std::string conf_file = Core::Wukong_Get_System().get_conf_name();
std::string kernel_name = "";
std::string fs_name = "";
Core::u32 fs_addr = 0;
Core::Wukong_Get_System().load_config(arch_name, conf_file);
Core::Config_File * cf = Core::Wukong_Get_System().get_config();
cf->read("/kernel/name", kernel_name);
cf->read("/filesystem/name", fs_name);
cf->read("/filesystem/address", fs_addr);
load_fs(fs_name, fs_addr);
return true;
}
void Board_AT91EV40::on_create()
{
name_ = "AT91EV40(AT91X40)";
Core::Board<Core::u32>::on_create();
}
Core::Memory_Result Board_AT91EV40::io_dispatch(Core::Memory_Access_Type type, Core::u32 start, \
size_t size, Core::Bytecode_Type & buffer)
{
switch(type)
{
case Core::Memory_32Bit::MEMORY_READ:
return io_read_word(start, size, buffer);
// return Core::Dummy_MMU<Core::u32>::MEMORY_SUCCESSFUL;
case Core::Memory_32Bit::MEMORY_WRITE:
return io_write_word(start, size, buffer);
// return Core::Dummy_MMU<Core::u32>::MEMORY_SUCCESSFUL;
default:
return Core::Dummy_MMU<Core::u32>::MEMORY_ACCESS_VIOLATION;
}
}
Core::Memory_Result Board_AT91EV40::io_read_word(Core::u32 start, size_t size, \
Core::Bytecode_Type & buffer)
{
static Core::u32 isr2_4=0;
if(start == 0xfff00000)
{
Core::Wukong_Get_System().convert_to_bytecode(0x14000040,buffer);
return -1;
}
if(start>=0xFFFD0000 && start<=0xFFFD3FFF) //UART0
{
uart_->on_mapped_memory_read(start, size, buffer);
}
else if(start>=0xFFFA0000 && start<=0xFFFA007C)//nic8019
{
nic8019_->on_mapped_memory_read(start,1,buffer);
}
//aic's address,this is a watch dog
else if(start >= 0xfffff000 && start <= 0xfffff134)
{
switch(start)
{
case 0xfffff100: // IRQ Vector Register
//2.4中还要读isr以验证中断,请在0xfffff108中增加相应代码
if(aic_reg_[AIC_ISR] & 0x00010000)
{
Core::Wukong_Get_System().convert_to_bytecode((Core::u32)16, buffer);
//clear(AIC_ISR); //clear zero
isr2_4 = aic_reg_[AIC_ISR];
aic_reg_[AIC_ISR] = aic_reg_[AIC_ISR] & ~0x00010000;
}
else if(aic_reg_[AIC_ISR] & 0x00000020)//clock
{
//get_host_machine()->convert_to_bytecode(temp, buffer);
Core::Wukong_Get_System().convert_to_bytecode((Core::u32)5, buffer);
//clear(AIC_ISR); //clear zero
isr2_4 = aic_reg_[AIC_ISR];
aic_reg_[AIC_ISR] = aic_reg_[AIC_ISR] & ~0x00000020;
}
else if( aic_reg_[AIC_ISR] & 0x00000010)
{
//get_host_machine()->convert_to_bytecode(temp, buffer);
Core::Wukong_Get_System().convert_to_bytecode((Core::u32)4, buffer);
//clear(AIC_ISR); //clear zero
isr2_4 = aic_reg_[AIC_ISR];
aic_reg_[AIC_ISR] = aic_reg_[AIC_ISR] & ~0x000000010;
}
else if(aic_reg_[AIC_ISR] & 0x00000040 )
{
//get_host_machine()->convert_to_bytecode(temp, buffer);
Core::Wukong_Get_System().convert_to_bytecode((Core::u32)6, buffer);
//clear(AIC_ISR); //clear zero
isr2_4 = aic_reg_[AIC_ISR];
aic_reg_[AIC_ISR] = aic_reg_[AIC_ISR] & ~0x00000040;
}
else if(aic_reg_[AIC_ISR] & 0x00000004)// input
{
Core::Wukong_Get_System().convert_to_bytecode((Core::u32)2, buffer);
//clear(AIC_ISR); //clear zero
isr2_4 = aic_reg_[AIC_ISR];
aic_reg_[AIC_ISR] = aic_reg_[AIC_ISR] & ~0x00000004;
}
//else if( aic_reg_[AIC_ISR] & 0x00000004 )//net card
else
{
Core::Wukong_Get_System().convert_to_bytecode((Core::u32)0, buffer);
}
break;
case 0xfffff108:
//aic_reg_[AIC_ISR] = 0x20;
if(isr2_4 & 0x00010000)
{
Core::Wukong_Get_System().convert_to_bytecode(16, buffer);
isr2_4 = 0;
}
else if( isr2_4 & 0x00000020 )
{
Core::Wukong_Get_System().convert_to_bytecode(5, buffer);
isr2_4 = 0;
//aic_reg_[AIC_ISR] = aic_reg_[AIC_ISR] & ~0x00000020;
}
else if(isr2_4 & 0x00000004)
{
Core::Wukong_Get_System().convert_to_bytecode((Core::u32)2, buffer);
isr2_4 = 0;
}
else
{
Core::Wukong_Get_System().convert_to_bytecode(0, buffer);
}
break;
case 0xfffff110://Interrupt Mask Register
Core::Wukong_Get_System().convert_to_bytecode(aic_reg_[AIC_IMR], buffer);
break;
default:
assert(0);
break;
}
}
else
{
Core::Wukong_Get_System().convert_to_bytecode(-1,buffer);
}
return Core::Dummy_MMU<Core::u32>::MEMORY_SUCCESSFUL;
}
Core::Memory_Result Board_AT91EV40::io_write_word(Core::u32 start, size_t size, Core::Bytecode_Type & buffer)
{
if(start>=0xFFFD0000 && start<=0xFFFD3FFF) //UART0
{
uart_->on_mapped_memory_write(start, size, buffer);
}
else if(start>=0xFFFA0000 && start<=0xFFFA007C)//nic8019
{
nic8019_->on_mapped_memory_write(start,1,buffer);
}
else if(start >= 0xfffff000 && start <= 0xfffff134)//aic's address
{
Core::u32 target = 0;
Core::Wukong_Get_System().convert_from_bytecode(buffer, target);
switch(start)
{
case 0xfffff120://Enable Command Register
for(Core::u32 i = 0; i<32; i++)
{
if(target & 1 << i)
aic_reg_[AIC_IMR] |= (1 << i);
}
break;
case 0xfffff124://Disable Command Register
for(Core::u32 i = 0; i<32; i++)
{
if(target & 1 << i)
aic_reg_[AIC_IMR] &= ~(1 << i);
}
break;
case 0xfffff128: //Clear Command Register
for(Core::u32 i = 0; i<32; i++)
{
if(target & 1 << i)
aic_reg_[AIC_ISR] &= ~(1 << i);
}
break;
case 0xfffff108:
aic_reg_[AIC_ISR] = 0;
break;
}
}
else
{
return Core::Dummy_MMU<Core::u32>::MEMORY_IO_RW;
}
return Core::Dummy_MMU<Core::u32>::MEMORY_SUCCESSFUL;
}
void Board_AT91EV40::io_do_cycle(void)
{
descend_io_prescale();
if(test_io_prescale())
{
reset_io_prescale();
Core::u32 & rcr = ((DEVICE::UART *)uart_)->get_rcr();
Core::u32 & rpr = ((DEVICE::UART *)uart_)->get_rpr();
if( rcr > 0 )
{
if(is_kb_input())
{
is_kb_input_ = true;
char buf[16];
Core::s32 n = kb_read(0, buf, rcr > sizeof(buf) ? sizeof(buf) : rcr);
Core::Bytecode_Type vbuf(4);
for (Core::s32 i = 0; i < n; i++, rcr--, rpr++)
{
vbuf.at(0) = ((Core::u8)buf[i]);
//uart_->on_mapped_memory_write(rpr, 1, vbuf);
Core::MMU<Core::u32> & mmu = ((Core::CPU_32Bit *)Core::Wukong_Get_System().get_cpu())->get_mmu();
mmu.access(Core::Memory_32Bit::MEMORY_WRITE, rpr, 1, vbuf);
}
}
}
if(is_nic8019_)
{
//lijc add nic input handler
if(nic8019_->get_state())
{//在get_state里实现从物理网络取数据到网卡缓冲
is_nic_input_ = true;
}
}
}
}
Core::Interrupt_Type Board_AT91EV40::get_highest_interrupt(void)
{
descend_clock();
if(is_kb_input_)
{
is_kb_input_ = false;
return Board_AT91EV40::UXINT_sig;
}
//lijc add
else if(is_nic_input_)
{
is_nic_input_ = false;
return Board_AT91EV40::NIC_sig;
}
else if( clock == 0 )
{
reset_clock();
return Board_AT91EV40::CLOCK_INT;
}
else
{
//clock--;
set_signal(Board_AT91EV40::IRQ_sig, false);
return Inter_Undefined;
}
//else
//return Inter_Undefined;
}
void Board_AT91EV40::on_interrupt(Core::Interrupt_Type type)
{
switch(type)
{
case Board_AT91EV40::CLOCK_INT:
if( aic_reg_[AIC_IMR] >> 5)
{
aic_reg_[AIC_ISR] |= 0x00000020;
signal_[IRQ_sig] = true;
}
else if( aic_reg_[AIC_IMR] >> 4)
{
aic_reg_[AIC_ISR] |= 0x00000010;
signal_[IRQ_sig] = true;
}
else if( aic_reg_[AIC_IMR] >> 6 )
{
aic_reg_[AIC_ISR] |= 0x00000040;
signal_[IRQ_sig] = true;
}
break;
case Board_AT91EV40::UXINT_sig:
aic_reg_[AIC_ISR] |= 0x00000004;
if(aic_reg_[AIC_IMR] >> 2)
signal_[IRQ_sig] = true;
break;
//lijc
case Board_AT91EV40::NIC_sig:
if( (aic_reg_[AIC_IMR]>>16) &&!(aic_reg_[AIC_ISR]&0x00010000))
{
aic_reg_[AIC_ISR] |= 0x00010000;
signal_[IRQ_sig] = true;
}
if(!(aic_reg_[AIC_IMR]>>16))
{
//std::cout<<__FILE__<<__LINE__<<"网卡中断没开"<<aic_reg_[AIC_IMR]<<std::endl;
//exit(1);
}
break;
default:
// signal_[IRQ_sig] = false;
break;
}
}
void Board_AT91EV40::poll_extern_exception()
{
Core::Register &cpsr = cpu_->get_cpsr();
//Board_AT91EV40 *board = (Board_AT91EV40 *)Core::Wukong_Get_System().get_board();
CPU_7TDMI::CPU_Interrupt current_exp_priority = cpu_->get_exp_priority();
if(current_exp_priority > 3 || current_exp_priority < 0)
{
if( test_signal(Board_AT91EV40::FIQ_sig) \
&& !cpsr.test(6) )
{
cpu_->do_exception(CPU_7TDMI::FIQ_exp);
set_signal(Board_AT91EV40::FIQ_sig, false);
}
}
//if(current_exp_priority > 4 || current_exp_priority < 0 || 1)
//attention 暂时这样子 lijc
{
if( test_signal(Board_AT91EV40::IRQ_sig) \
&& !cpsr.test(7) )
{
cpu_->do_exception(CPU_7TDMI::IRQ_exp);
set_signal(Board_AT91EV40::IRQ_sig, false);
}
}
}
#ifdef LINUX
Core::s32 Board_AT91EV40::kb_input()
{
fd_set rfds;
struct timeval tv;
FD_ZERO(&rfds);
FD_SET(0, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 0;
return select(0+1, &rfds, NULL, NULL, &tv) ;
}
#endif
#ifdef WIN32
Core::s32 Board_AT91EV40::kb_read(Core::s32 fd,char *buffer, Core::s32 count)
{
///* Core::u32 i;
// for( i = 0; (i< count) && kbhit(); i++)
// {
// buffer[i] = getch();
// if( buffer[i] == '\r')
// buffer[i] = '\n';
// }*/
// return i;
size_t size = Core::Wukong_Get_System().get_key_event_count();
if (size == 0)
return 0;
for (size_t i = 0; i < size && i < count; ++i)
{
Core::System::Key_Event evt = Core::Wukong_Get_System().top_key_event();
Core::Wukong_Get_System().pop_key_event();
buffer[i] = (char)evt.keycode;
if( buffer[i] == '\r')
buffer[i] = '\n';
}
return i;
}
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -