Typical methods and problems of input and output I/O devices in embedded design - busy waiting and interrupts

The work was first published on my personal blog

www.thedreamfish.cn

Classic input and output devices

Input/output devices often have analog or non-electrical components. Obviously we can realize that the CPU communicates with the device by reading and writing registers. These devices usually have the following registers.

  • Data register: Saves data to be processed or processed by the device.
  • Status register: Provides various status registers for device operation.

PCF8591

Here we use the PCF8591 learned in the 51 microcontroller as an example and explain its operation words.

Operation word

  • PCF8591 is an 8-bit AD/DA conversion chip with an I2C bus interface. It is powered by a single power supply (2.5~6V) internally, with a typical value of 5V, and is produced using CMOS technology. PCF8591 has 4 channels of AD inputs, which are of the successive comparison type and contain a sample and hold circuit; 1 channel of 8-bit DA output contains a DAC data register. The maximum rate of AD/DA conversion is approximately 11KHz.
  • In the IICa bus, the device address must be sent as the first byte after the start condition. The second byte sent to the PCF8591 is stored in the control register and is used to control the register's functionality. The third byte sent to the PCF8591 is stored into the DAC data register. And use the on-chip D/A to convert it into the corresponding analog voltage.
  • An A/D conversion cycle always starts after sending a valid read mode address to the PCF8591. The A/D conversion cycle is triggered on the trailing edge of the acknowledge clock pulse. The operation is divided into four steps:
    • Send the address byte to select the device.
    • Send control bytes to select the corresponding channel.
    • Resend the address byte, selecting the device.
    • Receive data from the target channel.

Function description

  • Each PCF8591 in the I2C bus system is activated by sending a valid address to the device. The address includes a fixed part and a programmable part. The programmable part must be set according to the addresses A0 A2 A2. In the I2C bus protocol, the address must be sent as the first byte after the knight condition. The last bit of the address byte is used to set the read/write bit for the direction of subsequent data transfer.

Insert image description here

  • The second byte sent to the PCF8591 will be stored in the control register. Used to control device functions.

    • The specific register configuration (instructions) will not be introduced in detail. The summary is as follows:

      To configure the adc function, send 0x90, 0x40+channel (values ​​0, 1, 2, 3, a total of four channels), and 0x91;

      To configure the dac function, just send 0x90, 0x40, user_data (8bit) successively;

Read and write source code

import smbus
import time
bus = smbus.SMBus(1)
#check your PCF8591 address by type in 'sudo i2cdetect -y -1' in terminal.
def setup(Addr):
	global address
	address = Addr

def read(chn): #channel
	if chn == 0:
		bus.write_byte(address,0x40)
	if chn == 1:
		bus.write_byte(address,0x41)
	if chn == 2:
		bus.write_byte(address,0x42)
	if chn == 3:
		bus.write_byte(address,0x43)
	bus.read_byte(address) # dummy read to start conversion
	return bus.read_byte(address)

def write(val):
	temp = val 
	temp = int(temp) # change string to integer
	bus.write_byte_data(address, 0x40, temp)

if __name__ == "__main__":
	setup(0x48)
	while True:
		print 'AIN0 = ', read(0)
		print 'AIN1 = ', read(1)
		tmp = read(0)
		tmp = 5*(tmp/255)
		write(tmp)
#		time.sleep(0.3)

Input/output primitives

Microprocessors can provide programming support for input and output in two ways: I/O instructions and memory-mapped I/O. The X86 we learned earlier provides input and output (in and out). These instructions provide a separate address space for I/O devices.

In our ARM system, the most common method is through memory mapping - even the CPU that provides I/O instructions can implement memory mapping. This provides a memory address for each I/O device. Programs use general CPU read and write commands to communicate with the device.

Read operation

#define DEV1 0x100
int peek(char *location){
    
    
	return *location;
}

DEV1  EQU OX100
LDR r1,#DEV1
LDR r0,[r1]

write operation

#define DEV1 0x100
void poke(char *location, char new){
    
    *location)=new;
}

DEV1 EQU 0X100
LDR r1,#DEV1;
LDR r0,#8
STR r0,[r1]

How the CPU and peripherals interact

Busy I/O

The simplest way to use a device in a program is to busy wait for I/O. We know that if the CPU performs multiple operations on a device, such as writing a number of characters to an output device, it must wait for the previous operation to end before it can enter the next operation. So we can never start writing the second character before the first string is written, and the peripheral will never respond. Therefore it is extremely important to ask if the device is idle by querying the status register

Output source code

#define out_char 0X100
#define out_status 0x101
char *mystring = "helloworld";
char *current_char;
current_char=mystring;
while (current_char = '/0'){
    
    
  poke (out_char,*current_char);
  poke(out_status,1);//打开输出设备
  while (peek(out_status)!=0);//外设状态寄存器为1时表示正在写
  current_char++;
}

output after input

//当新字符被读取时,输入设备状态为1,读取后,设置为0,就可以开始新的读取
//写字符,将输出状态设置为1,启动,为0时才可以再一次输出
#define in_data 0x100
#define in_status 0x101
#define out_data 0x110
#define out_status ox111
while (1){
    
    
  while (peek(in_status)==0){
    
     //读取状态寄存器
    tmp= (char)peek(in_data);
  }
  poke(out_data,char);
  poke(out_status,1);
  while (peek(out_status)!=0);
}

interrupt

We can find that using busy wait will cause the CPU to fall into an extremely troublesome state. The CPU has to spend a lot of energy to continuously query the status of the register, and is unable to deal with other potentially more important things. In order to allow the CPU to control other I/O devices in the process, or to determine the next output data to be sent to the device or to process the last accepted input, calculation operations are performed.

The author encountered this when participating in an electronic design competition. If the ADC/DAC is not interrupted and the DMA sampling technology is not used, not only will the CPU have strange delay problems during operation, but it will also affect the sampling rate accuracy. not tall. Especially when using DAC output, only after using interrupts and dma processing can we find that this can be greatly reduced.

Obviously sometimes, although interrupts have the advantages of real-time and quick response, we know that in fact we cannot always interrupt the work of the CPU. Interrupting the work of the CPU frequently will destroy the stability of a series of tasks such as the assembly line. sex.

Interruption expenses

interrupted process
  • The CPU checks for pending interrupts at the beginning of the instruction. It responds to the highest priority interrupt.

  • After receiving the interrupt response signal, the device will send the interrupt vector to the CPU.

  • The CPU uses the vector as an index to find the address of the interrupt service routine in the interrupt vector table. And protect the interrupt site and save the state of the cpu register.

  • The software will drive and save other CPU states, then perform the operations required by the device, and finally execute the interrupt.

  • The CPU will restore the PC and other automatically saved states, return to the interrupted code and continue execution.

ARM7 responds to interrupt
  • Save the appropriate pc value.
  • copy cpsr to spsr
  • Force bits in cpsr to log interrupts
  • Force pc to point to interrupt vector
ARM7 end interrupt
  • Restore the correct value of pc
  • restore cpsr with spsr
  • Clear interrupt disable flag
Interrupt overhead

Interruptions result in the loss of branches. Additional clock cycles are required to respond to interrupts, and the interrupt routine needs to continuously protect and restore registers that are automatically saved without interrupts. The time it takes for the hardware to find an interrupt and find an interrupt vector cannot be determined by the programmer.

Interrupt source code

/*
字符串io_buff保存那些已经读入但是未能写出的字符队列。
当新字符被读取时,输入设备状态为1,读取后,设置为0,就可以开始新的读取
写字符,将输出状态设置为1,启动,为0时才可以再一次输出
我们已经具有下面这些函数
*/
#define buf_size 8
void add_char(char x);
char remove_char();
bool enpty();
bool full();

#define in_data 0X100
#defien in_status 0x101
#define out_data 0x110
#define out_status 0x101

void input_hander(){
    
    
  char tmp;
  tmp=peek(in_data);
  add_char(tmp);
  poke (in_status,0);
  
  if (nchar()==1){
    
    
    poke(out_data,remove_char());
    poke(out_status,1);
  }
}
如果io_buff有字符在等待,输出设备可以自行开启一个输出设备
否则必须有输入设备在其中断程序中启动输出设备。


//输出一个字符串后触发中断
void output_handere(){
    
    
   if (empty()){
    
    
     poke(out_data,remove_char());
     poke(out_atatus,1);
   }
}


//另一种写法
void input hander(){
    
    
  achar=peek(in_data);
  where=1
  poke(in_status,0);
}

int main(){
    
    
	while(1){
    
    
  	if (where){
    
    
      poke(out_data,achar);
      poke(out_status,1);
      where=0;
    }
}}
//1.输入输出的速度可能不一样
//前台参与了工作

Management, exceptions and traps

abnormal

An exception is an internally detectable error. A classic example is division by zero, undefined resets instructions and illegal memory access. Exceptions must have priority because one operation may generate many exceptions. The vector of exceptions is usually predefined by the architecture; it is used to index the exception handler table.

trap

When software is interrupted, it usually enters the pipe state. If the interface between the user and the pipe state is not carefully designed, the user program may secretly enter the pipe state and cause damage.

management

Programs usually run in user mode, and supervisor mode has higher privileges. For example, allowing dynamic changes to the physical address of a memory unit. In this mode, the last five bits of cpsr are all set to 1.


Guess you like

Origin blog.csdn.net/xrk00/article/details/122510584