(1) The Concept of Address
1) Physical Address: The address generated by the CPU’s address bus is controlled by the hardware. A large portion of this physical address space is reserved for RAM, but it may also be mapped to other memory types like video memory or BIOS. After a program's virtual address goes through segment and page mapping, it results in a physical address that is sent to the CPU's address lines.
The physical address space is determined by the system's hardware design. For example, a 32-bit x86 processor has a physical address space of 4GB (2^32). However, the actual RAM installed on a PC usually does not reach this limit because some addresses are reserved for peripheral devices connected via the bus. Typically, lower physical addresses are used for RAM, while higher ones are assigned to buses and peripherals.
2) Bus Address: This refers to the address used on the system bus during data transfers. Peripheral devices use bus addresses, while the CPU uses physical addresses. In the x86 architecture, the physical address and the bus address are often the same, as they share the same address space. This simplifies communication between the CPU and peripherals. On other architectures, however, a conversion or mapping might be necessary to translate between these two address spaces.
3) Virtual Address: Modern operating systems use virtual memory management, which relies on the MMU (Memory Management Unit) to translate virtual addresses into physical ones. If the MMU is enabled, the CPU sends virtual addresses to the MMU, which then maps them to physical addresses. Without an MMU, the CPU directly accesses physical memory. In Linux, each process has its own 4GB virtual address space, typically divided into user space (0–3GB) and kernel space (3–4GB).
When a CPU fetches instructions or reads data, it uses virtual addresses. The MMU translates these to physical addresses using page tables, allowing the CPU to access the correct memory location.
(2) Addressing Methods
1) Accessing Peripherals: Peripherals are accessed by reading and writing to their registers, known as I/O ports. There are two main addressing methods: independent addressing and unified addressing.
Unified Addressing: In this approach, I/O ports are treated like regular memory locations. They occupy a portion of the memory address space, making it easier for the CPU to access them. However, this reduces the available memory for other purposes. Unified addressing is common in architectures like PowerPC and m68k.
Independent Addressing: Here, I/O ports have their own separate address space, distinct from the main memory. The CPU uses special instructions like IN and OUT to access these ports. This method is typical in x86 systems, where the I/O address space is limited to 64KB (0x0000–0xFFFF).
2) Memory-Mapped I/O (MMIO): Some systems map I/O ports into the memory address space, allowing the CPU to access them using standard memory read/write operations. This is commonly used in PCI devices and modern embedded systems. It simplifies driver development by treating I/O as regular memory.
(3) Summary of Addressing Methods Across Architectures
Most peripheral devices are accessed through their registers, which can be either I/O ports or memory-mapped. The way the CPU accesses these depends on the architecture. For example, x86 uses separate I/O address space, while ARM and PowerPC typically use memory-mapped I/O.
In x86 systems, accessing I/O ports requires special instructions, while in RISC-based systems, I/O is often accessed via memory-mapped addresses. Linux abstracts these differences, providing functions like inb(), outb(), ioread(), and iowrite() to handle both I/O port and memory-mapped access.
(4) Difference Between I/O Port and I/O Memory
I/O ports and I/O memory are both used to communicate with peripherals, but they differ in how they are addressed and accessed. I/O ports are part of a separate address space (like the x86 I/O space), while I/O memory is part of the main memory space. In Linux, drivers must request and manage these resources properly to avoid conflicts.
For example, on x86, I/O ports are accessed using IN and OUT instructions, while I/O memory is accessed via memory-mapped regions. On ARM or PowerPC, I/O is usually memory-mapped, so drivers can treat it like regular memory.
(5) Access Methods for I/O Ports and I/O Memory in Linux
Linux provides several functions to access I/O ports and memory. For I/O ports, functions like inb(), outb(), and ioport_map() are used. For I/O memory, ioremap() is used to map physical addresses to kernel virtual addresses, after which functions like ioread8() and iowrite8() can be used.
Drivers should always request resources using request_region() or request_mem_region(), and release them using release_region() or release_mem_region(). This ensures that no two drivers conflict over the same I/O address range.
In summary, understanding the differences between physical, bus, and virtual addresses, along with the various addressing methods, is crucial for developing low-level drivers and working with hardware in operating systems like Linux.
Elf Bar 600,Elf Bar 600Puff,Elf Bar 600 Flavors,Elf Bar 600 Price
YIWU JUHE TRADING COMPANY , https://www.nx-vapes.com