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

📄 board_at91ev40.cpp

📁 浙江大学的悟空嵌入式系统模拟器
💻 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 + -