What is the development environment you have used?
Processor used: Dual core, cortex A9, IVA3 multimedia hardware, 32 bit dual channel, NEON inetgrated
Zebra terminals,
What is the boot process it has?
- Power the terminal and with clock in
- ROM Bootloader(RBL) configure watchdog timer, configure interl clock structure for conservative fixed rate
- ROM is programmed by factory and has fix set of boot options like booting from uart or ethernet
- In finished product it is configured to boot linux from non volatile memory like nand
- NOR is XIP so doesn’t require to copy code into memory to execute
- If boot fail for RBL it try other sources in sequencial order to try to load SBL
- RBL check boot mode pin to determine from where SBL need to be loaded. RBL load SPL from 0 offset of NAND flash. There are four copies of SBL present to counter the effect of bad block problem in NAND. RBL also takes care of bit error or correction to counter NAND property of getting corrupted over a period of time
- For other memody except NOR, RBL copies U-Boot or Special Boot Loader(SBL) (if uboot size is more than SBL) to internal memory like SRAM and execute it
- SBL loads UBOOT into external memory
- SBL configure clock and ram, conroller and uart to have debug message
- Uboot copies the linux kernel to external memory to give control to it.
- Linux kernel initialize any peripheral whose driver is required, any peripheral configured by UBOOT will be reconfigured by linux kernel
- Is any new component added in linux, it has to be present or updated in both uboot and kernel
How do you port on to a board in linux?
- Find out development board which is closly related with your product. During we design custom board
- Also we should choose hardware component part of development board
- Significant effort in porting of driver so we should deviate from development board only if absolutely needed
- Find out difference reference hardware and custom design like may be lcd and audio output
- Generally any soc manufacturer develop linux bsp for their soc i.e. most driver is already developed
- Here for new custom hardware you need to modify driver for lcd and audio output
- Both custom board and development board uses cortex-a9 and soc ompa 4430
- Linux has three layer 1. Architecture 2. System on chip 3. Board also called platform, machine and board respectively
- The layers are in three diff directory names platform, machine and board
- This helps in porting process as it separates code which doesn’t need to be modified.
- These three layers sit atop on linux shared code which is not changed for other processor like x86 or desktop
- Layer
- Machine layer - device specific layer and contains majority of device drivers corresponding to various SOC peripheral. Generally these drivers will be independent of board-specific hardware and require limited modification for configuring driver to external devices. Also it may need to modify driver code
- Board layer: we do lot of work here. Load code doesn’t need modification on new target. The step will begin with bringup power and clocking subsystem along with gpio or serial port in order to bring up. Later USB and ethernet. For debugging purposes. Modifying pin multiplexing and device clocking configuration need to be checked.
- Contains various drivers along with PLL and power management routines are located as well.
- Contains initialization data specific to various board components external to linux device
- For audio and lcd hardware need modification of driver source code in machine layer
What is bottom half and top half in interrupt handling?
The big difference between the top-half handler and the bottom half is that all interrupts are enabled during execution of the bottom half
In the typical scenario, the top half saves device data to a device-specific buffer, schedules its bottom half, and exits
The bottom half then performs whatever other work is required, such as awakening processes, starting up another I/O operation, and so on. This setup permits the top half to service a new interrupt while the bottom half is still working.
Ex: When an operating system is interrupted because of a hardware event (such as the presence of a packet through a network adapter), the processing begins in an interrupt.
processing done in the interrupt context is called the top half, and interrupt-based processing that's pushed outside of the interrupt context is called the bottom half
What is diff between tasklet and work queues?
Tasklets provide a low-latency mechanism that is simple and straightforward, while work queues provide a flexible API that permits queuing of multiple work items.
Each defers work from the interrupt context, but only tasklets run atomically in a run-to-complete fashion, where work queues permit handlers to sleep, if necessary.
What is char driver and how to load it?
Character device drivers normally perform I/O in a byte stream. Examples of devices using character drivers include tape drives and serial ports.
Describe linux folder structure.
- arch-This subdirectory contains all of the architecture-specific code. For each supported architecture (MIPS, ARM, 386, and so on), there is a subdirectory under "arch". Each supported architecture subdirectory has four major subdirectories:
- kernel, which contains the architecture-specific kernel code
- mm, which contains the architecture-specific memory management code
- lib, which contains architecture specific library code (vsprintf and so on)
- MY_PLATFORM (target platform directory), which contains platform-specific code.
Note that Linux ports to processors without memory management units (MMU) are also available
- documentation-This subdirectory contains the documentation for the kernel
- drivers-This subdirectory contains code for the device drivers. Each type of device has further subdirectories, such as char, block, net, and so on
- fs-This directory contains the file system code. This has further sub-directories for each supported file system (ext2, proc, and so on)
- include-The include subdirectory contains the include files for the kernel. It has further subdirectories for common include files (for all architectures), one for every architecture supported, and a couple of other subdirectories
- init-This directory contains the initialization code for the kernel
- kernel-This directory contains the main kernel code
- lib-This directory contains the library code of the kernel
- mm-This directory contains the memory management code
How to register and access char driver?
Loading and unloading modules
static int my_init(void){
return 0;
}
static void my_exit(void){
return;
}
module_init(my_init);
module_exit(my_exit);
|
Registering character device
Linux systems have a way of identifying device files via major device numbers, which identify modules serving device files or a group of devices, and minor device numbers, which identify a specific device among a group of devices that a major device number specifies.
register_chrdev (unsigned int major,
const char * name,
const struct fops);
file_operations *
struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*write) (struct file *, const char *, size_t, loff_t *); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, struct dentry *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); }; |
Specifying a name of the device
The file_operations structure
static struct file_operations simple_driver_fops = { .owner = THIS_MODULE, .read = device_file_read, };
static int register_device(void)
{
int result = 0;
printk( KERN_NOTICE "Simple-driver: register_device() is called." );
result = register_chrdev( 0, device_name, &simple_driver_fops );
if( result < 0 )
{
printk( KERN_WARNING "Simple-driver: can\'t register character device with errorcode = %i", result );
return result;
}
device_file_major_number = result;
printk( KERN_NOTICE "Simple-driver: registered character device with major number = %i and minor numbers 0...255"
, device_file_major_number );
return 0;
}
|
Using memory allocated in user mode
static ssize_t device_file_read(
struct file *file_ptr
, char __user *user_buffer
, size_t count
, loff_t *position)
{
printk( KERN_NOTICE "Simple-driver: Device file is read at offset = %i, read bytes count = %u"
, (int)*position
, (unsigned int)count );
/* If position is behind the end of a file we have nothing to read */
if( *position >= g_s_Hello_World_size )
return 0;
/* If a user tries to read more than we have, read only as many bytes as we have */
if( *position + count > g_s_Hello_World_size )
count = g_s_Hello_World_size - *position;
if( copy_to_user(user_buffer, g_s_Hello_World_string + *position, count) != 0 )
return -EFAULT;
/* Move reading position */
*position += count;
return count;
}
|
Build system of a kernel module
obj-m := module_name.o
module_name-objs := source_1.o source_2.o … source_n.o
make –C KERNEL_MODULE_BUILD_SYSTEM_FOLDER M=`pwd` modules
make modules_prepare
|
Loading and using a module
TARGET_MODULE:=simple-module
# If we are running by kernel building system
ifneq ($(KERNELRELEASE),)
$(TARGET_MODULE)-objs := main.o device_file.o
obj-m := $(TARGET_MODULE).o
# If we running without kernel build system
else
BUILDSYSTEM_DIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
all :
# run kernel build system to make module
$(MAKE) -C $(BUILDSYSTEM_DIR) M=$(PWD) modules
clean:
# run kernel build system to cleanup in current directory
$(MAKE) -C $(BUILDSYSTEM_DIR) M=$(PWD) clean
load:
insmod ./$(TARGET_MODULE).ko
unload:
rmmod ./$(TARGET_MODULE).ko
endif
cat /dev/simple-driver
Hello world from kernel mode! |
How to define driver function?
How to access driver?
What is page table?
What is little endian and big endian and how it helps?
Little Endian and Big endian are two ways of storing multi-byte data-types ( int, float, etc) in computers.
In Little Endian machines, last byte of binary representation of the multi-byte data-type is stored first while in Big Endian machines, first byte of binary representation of the multi-byte data-type is stored first.
Suppose an integer is stored as 4 bytes(32-bits), then a variable y with value 0x01234567.
In “Little Endian” form, assembly language instructions for picking up a 1, 2, 4, or longer byte number proceed in exactly the same way for all formats: first pick up the lowest order byte at offset 0. Also, because of the 1:1 relationship between address offset and byte number (offset 0 is byte 0), multiple precision math routines are correspondingly easy to write.
In “Big Endian” form, by having the high-order byte come first, you can always test whether the number is positive or negative by looking at the byte at offset zero. You don’t have to know how long the number is, nor do you have to skip over any bytes to find the byte containing the sign information. The numbers are also stored in the order in which they are printed out, so binary to decimal routines are particularly efficient.
Diff between page table and TLB?
How does linux kernel boots?
The bootloader is a piece of code responsible for Basic hardware initialization
Loading of an operating system kernel, from flash storage, from the network, or from another type of non-volatile storage.
- decompression of the kernel
- Run of kernel
- most bootloaders provide a shell with various commands implementing different operations.
- Loading of data from storage or network, memory inspection, hardware diagnostics and testing, etc.
When powered, the CPU starts executing code at a fixed address
The hardware design must ensure that a NOR flash chip is wired so that it is accessible at the address at which the CPU starts executing instructions ▶ The first stage bootloader must be programmed at this address in the NOR ▶ NOR is mandatory, because it allows random access, which NAND doesn’t allow ▶ Not very common anymore (unpractical, and requires NOR flash)
The CPU has an integrated boot code in ROM
- BootROM on AT91 CPUs, “ROM code” on OMAP, etc.
- This boot code is able to load a first stage bootloader from a storage device into an internal SRAM (DRAM not initialized yet)
- Storage device can typically be: MMC, NAND, SPI flash, UART (transmitting data over the serial line), etc.
- The first stage bootloader is
- Limited in size due to hardware constraints (SRAM size)
- Provided either by the CPU vendor or through community projects
This first stage bootloader must initialize DRAM and other hardware devices and load a second stage bootloader into RAM
- ROM Code: tries to find a valid bootstrap image from various storage sources, and load it into SRAM or RAM (RAM can be initialized by ROM code through a configuration header). Size limited to <64 KB. No user interaction possible.
- X-Loader or U-Boot: runs from SRAM. Initializes the DRAM, the NAND or MMC controller, and loads the secondary bootloader into RAM and starts it. No user interaction possible. File called MLO.
- U-Boot: runs from RAM. Initializes some other hardware devices (network, USB, etc.). Loads the kernel image from storage or network to RAM and starts it. Shell with commands provided. File called u-boot.bin or u-boot.img.
- Linux Kernel: runs from RAM. Takes over the system completely (bootloaders no longer exists)
How to start porting linux kernel?
The GNU1 project provides a wealth of development tools that support Linux and are also open source. In addition, many device drivers are available for Linux, which could be used directly or as a starting point for your target devices.
Steps:
- cross-development tools need to be downloaded and installed on the PC running Linux: cross-binutils-as, ld, and so on; C cross compiler; and cross-development C libraries. The detailed steps for installation are available along with the tools.
- Linux kernel sources for MIPS can be downloaded from the Linux-VR site. One of the most important steps in porting Linux to a new target platform is to have a very clear understanding of how the kernel sources are organized
- Building the kernel image
- The Makefile in the $(TOPDIR) has to have ARCH (architecture) properly defined (MIPS in this case). The Makefile in $(TOPDIR)/arch/MY_ARCH/boot has to have CROSS_COMPILE (MIPS little-endian cross-compiler tool-set in this case) and LOADADDR (address at which the kernel image would be loaded) defined as per the configuration. If additional configuration options have to be added, the $(TOPDIR)/arch/MY_ARCH/config.in file has to be modified. You would need to have a config option for your platform (CONFIG_MYPLATFORM) to include code that is specific to your platform.
- The kernel has to be configured ("make config") to the barest minimum needs (serial driver, ramdisk driver, ext2 file system). Then do a "make dep" to set up the dependencies and finally a "make vmlinux" to produce the kernel image.
- Ramdisk
To begin with, a ramdisk can be mounted as the root file system. Ramdisk images and objects are also available readily for MIPS (Linux-VR site). A ramdisk image is a file that contains an image of an ext2 filesystem, while a ramdisk object is an elf object that encapsulates a ramdisk image and can be linked into the kernel. The ramdisk image is usually stored in compressed form. CONFIG_BLK_DEV_RAM and CONFIG_BLK_DEV_INITRD need to be defined as Y in "make config." The ramdisk image can be modified to include your applications, if required. Tools (scripts) are available at the Linux VR site for creating a ramdisk object. The ramdisk.o file needs to be copied to $(TOPDIR)/arch/MY_ARCH/boot and linked into the kernel. There is a detailed document, $(TOPDIR)/Documenta-tion/ramdisk.txt, on how to use the RAM disk block device with Linux.
- Processor-specific changes to the kernel code
If your processor is a standard (or popular) one, in most cases a Linux port to that processor would be available. The number of TLB3 (translation lookaside buffers) entries may be different for different implementations. Add a config option (CONFIG_MYCPU) to include code that is specific to your processor. Directories $(TOPDIR)/arch/MY_ARCH/kernel and $(TOPDIR)/arch/MY_ARCH/mm contain the processor-specific code that require modifications if you are dealing with a new implementation.
- Assembly file $(TOPDIR)/arch/MY_ARCH/kernel/head.S contains kernel_entry, the entry point for the kernel. This file also contains the exception handling code. Listing 1 shows the implementation of the kernel_entry routine in pseudocode.
- Install a cross-development environment.
- Setup the board and ensure that the serial port is working so we can print data through the serial port.
- Download and install the Linux kernel, most of the porting work will be done at this level.
- Add board specific code into the kernel tree.
- Build a kernel image to run on the board
- Test that early kernel printk is working
- Get the real printk working with the serial console.
- For a new board, a new board-specific directory should be added as well as support for interrupt handling, kernel timer services and mapping for memory areas.
- Ethernet drivers are usually the next drivers to focus on as they enable setup of NFS root file system to get access to user utilities and applications.
- Filesystem can be provided in different forms which are listed on LinuxFilesystem
Talk in brief about nand flash
What is function pointer and how we use it?
How uart driver implemented in linux? Provide info in brief?
Talk about UART protocol
The UART is the peripheral on the microcontroller which can send and receive serial data asynchronously, while RS-232 is a signalling standard.
UART peripherals typically have several configurable parameters required to support different standards. There are five parameters which must be configured correctly to establish a basic serial connection:
- Baud rate: Baud rate is the number of symbols or modulations per second. Basically, the baud rate indicates how many times the lines can change state (high or low) per second. Since each symbol represents one bit, the bit rate equals the baud rate. For example, if the baud rate is 9600, there are 9600 symbols sent per second and therefore the bit rate is 9600 bits per second (bps) .
- Number of data bits: The number of data bits transmitted is typically between 5 and 8, with 7 and 8 being the most common since an ASCII character is 7 bits for the standard set and 8 bits for the extended.
- Parity: The parity can be even, odd, mark or space. The UART peripheral calculates the number of 1s present in the transmission. If the parity is configured to even and the number of 1’s is even then the parity bit is set zero. If the number of 1s is odd, the parity bit is set to a 1 to make the count even. If the parity is configured to odd, and the number of 1s is odd, then parity bit is set to 0. Otherwise it is set to 1 to make the count odd. Mark and space parity mean that the parity bit will either be one or zero respectively for every transmission.
- Stop bits: The number of stop bits is most commonly configurable to either one or two. On some devices, half bits are supported as well, for example 1.5 stop bits. The number of stop bits determines how much of a break is required between concurrent transmissions.
- Endianess: Some UART peripherals offer the option to send the data in either LSB (least significant bit) or MSB (most significant bit). Serial communication of ASCII characters is almost always LSB.
What is function pointer and how to use it? How we use it in embedded system?
void fun(int a){
printf("Value of a is %d\n", a);
}
int main(){
void (*fun_ptr)(int) = fun; // & removed
fun_ptr(10); // * removed
}
function pointers can be used in task schedulers to dynamically call which function is executed from a task table.
They can be used in complex state machines or switch statement to decrease overhead of a decision and to break up states into manageable and maintainable chunks.
single-most important use of function pointers in embedded systems is to create vector tables.
MCU architectures use a table of addresses located in NVM, where each address points to an ISR (interrupt service routine). Such a vector table can be written in C as an array of function pointers.
What is Paging?
The important thing is to remind that system memory is divided into many pieces called pages.
Each process in a system lives in its address space. This one is composed of 4kB pages as well. For each process operating system kernel maintains a translations of process's pages (virtual) into physical ones.
Thanks to this mechanism it is possible to keep only one instance of code sections of programs in physical memory, easy share memory between processes, limit problem of memory fragmentation, use storage devices (such as disks) as swap area, use demand paging and copy on write (CoW) techniques
What is Page fault?
As mentioned in the introduction to this paper exceptions often are not harmful but they are part of various smart mechanisms. One of these is mechanism of physical memory allocation for user processes in UNIX systems.
Page fault exception is raised when memory management unit (MMU) inside CPU is not able to translate virtual address into physical one. For systems which don't use virtual memory or memory protection page fault usually means serious failure. At least for a thread which tried to execute an instruction which could not be completed.
What is Demand paging: malloc and physical memory?
By default malloc call does not allocate real physical memory. What it does it is only requests kernel for address space.
This means that no physical memory is allocated when doing malloc. What is done is only "adnotation" that calling process is permitted to reference some addresses.
When process tries to read or write previously malloced memory but no physical memory has been assigned yet then MMU is not able to translate virtual process address into physical one and page fault exception is raised. Now kernel (in exception handler) does a check whether accessed address is legal for process. If so it searches for free frame of physical memory and makes mapping. When the exception handler is done operating system may resume interrupted process. All these things are transparent to user process and does not require any action.
The important thing is to remind that system memory is divided into many pieces called pages.
Each process in a system lives in its address space. This one is composed of 4kB pages as well. For each process operating system kernel maintains a translations of process's pages (virtual) into physical ones.
Thanks to this mechanism it is possible to keep only one instance of code sections of programs in physical memory, easy share memory between processes, limit problem of memory fragmentation, use storage devices (such as disks) as swap area, use demand paging and copy on write (CoW) techniques
What is Page fault?
As mentioned in the introduction to this paper exceptions often are not harmful but they are part of various smart mechanisms. One of these is mechanism of physical memory allocation for user processes in UNIX systems.
Page fault exception is raised when memory management unit (MMU) inside CPU is not able to translate virtual address into physical one. For systems which don't use virtual memory or memory protection page fault usually means serious failure. At least for a thread which tried to execute an instruction which could not be completed.
What is Demand paging: malloc and physical memory?
By default malloc call does not allocate real physical memory. What it does it is only requests kernel for address space.
This means that no physical memory is allocated when doing malloc. What is done is only "adnotation" that calling process is permitted to reference some addresses.
When process tries to read or write previously malloced memory but no physical memory has been assigned yet then MMU is not able to translate virtual process address into physical one and page fault exception is raised. Now kernel (in exception handler) does a check whether accessed address is legal for process. If so it searches for free frame of physical memory and makes mapping. When the exception handler is done operating system may resume interrupted process. All these things are transparent to user process and does not require any action.
What is the difference between process and thread?
What is PCB?
information stored in PCB includes: 1. Process name (ID) 2. Priority 3. State (ready, running, suspended) 4. Hardware state (processor registers and flags) 5. Scheduling information and usage statistics 6. Memory management information 7. I/O status (allocated devices, pending operations) 8. File Management information (open files, access rights) 9. Accounting information
No comments:
Post a Comment