三,串口中断服务线程
串口中断产生以后,具体的数据处理将在中断服务线程里面完成,以BSP包中camera的中断线程为例
DWORD CameraCaptureThread(void)
{
unsigned char tmp=0;
static unsigned int time,old_time;
static unsigned int cam_intr;
DWORD dwCause;
//dwDisplayTimeout = INFINITE;
SetProcPermissions((DWORD)-1);
while(TRUE)
{
RETAILMSG(0,(TEXT("[CAM_HW] InterruptThread : Waiting For a Single Object\n\r")));
dwCause = WaitForSingleObject(CameraEvent, dwDisplayTimeout);
RETAILMSG(MSG_EN_1,(_T("CameraCaptureThread(%d)++\r\n"), frame_count));
if (dwCause == WAIT_OBJECT_0)
{
Lock();
__try
{
if (s2440INT->INTSUBMSK & ( 1 << IRQ_SUB_CAM_C ))
{
frame_count++;
cam_intr |= ( 1 << IRQ_SUB_CAM_C );
s2440INT->SUBSRCPND = (1<<IRQ_SUB_CAM_C);
s2440INT->INTSUBMSK &= ~(1<<IRQ_SUB_CAM_C);
//RETAILMSG(1,(_T("CAM_C, ts %d\r\n"), GetTickCount()));
}
if (s2440INT->INTSUBMSK & ( 1 << IRQ_SUB_CAM_P ))
{
cam_intr |= ( 1 << IRQ_SUB_CAM_P );
s2440INT->SUBSRCPND = (1<<IRQ_SUB_CAM_P);
s2440INT->INTSUBMSK &= ~(1<<IRQ_SUB_CAM_P);
//RETAILMSG(1,(_T("CAM_P, ts %d\r\n"), GetTickCount()));
}
if (((s2440INT->INTSUBMSK & ( 1 << IRQ_SUB_CAM_C )) == 0) && ((s2440INT->INTSUBMSK & ( 1 << IRQ_SUB_CAM_P )) == 0))
{
RETAILMSG(MSG_EN_1,(_T("[CAM]NOP\r\n")));
}
InterruptDone(g_CamSysIntr);
//time = GetTickCount();
//RETAILMSG(1,(TEXT("+time:%d\r\n"),(time - old_time)));
// Handle any interrupts on the input source
if (cam_intr & ( 1 << IRQ_SUB_CAM_P ))
{
// display the image
if (DRIVER_PREVIEW_ENABLE == 1)
Display_Cam_Image(LCD_XSIZE_TFT-PREVIEW_X,0,PREVIEW_X, PREVIEW_Y, PORT_A);
Buffer_preview_info_update();
cam_intr &= ~( 1 << IRQ_SUB_CAM_P );
}
if (cam_intr & ( 1 << IRQ_SUB_CAM_C ))
{
Buffer_codec_info_update();
cam_intr &= ~( 1 << IRQ_SUB_CAM_C );
}
// Enable camera interrupt
//s2440INT->INTSUBMSK &= ~(( 1 << IRQ_SUB_CAM_P )|( 1 << IRQ_SUB_CAM_C ));
//s2440INT->INTMSK &= ~( 1 << IRQ_CAM );
//old_time = GetTickCount();
//RETAILMSG(1,(TEXT("-time:%d\r\n"),(old_time-time)));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
RETAILMSG(PM_MSG, (TEXT("Camera.DLL:InterruptThread() - EXCEPTION: %d"), GetExceptionCode()));
}
Unlock();
}
else if (dwCause == WAIT_TIMEOUT)
{
Lock();
RETAILMSG(PM_MSG,(_T("[CAM_HW] InterruptThread Timeout : %d msec\r\n"), dwDisplayTimeout));
dwDisplayTimeout = INFINITE; // reset timeout until Camera Interrupt occurs
bIdlePwrDown = TRUE; // Codec is off
CamInterface_PowerDown();
RETAILMSG(PM_MSG, (TEXT("[CAM_HW] InterruptThread : bIdlePwrDown = TRUE\r\n")));
Unlock();
}
else
{
RETAILMSG(PM_MSG, (TEXT("[CAM_HW] InterruptThread : Exit %d, Cause %d\r\n"), GetLastError(), dwCause));
}
}
return 0;
}
WaitForSingleObject()函数等待中断事件的方式。既是用在串口中断线程初始化时绑定的事件和逻辑中断
。函数的第二个参数表示等待事件发生的时间,INFINITE表示一直等待。中断触发以后设置中断标志变量cam_intr并且进行开中断的操作。OAL层的中断函数在common目录下的intr.c中实现。子中断寄存器的控制可以在OAL目录下的intr.c中实现。
四,S3C2440A串口寄存器的配置
用到了串口的FIFO模式传输数据,所以关键是配置UFCON和UCON。UFCON设置串口FIFO的中断触发值,如图
第4为用于使能FIFO模式和复位FIFO,高4位设置中断触发值,要是设置成0 ,就相当于没有使用FIFO模式。
UCON中和FIFO相关的是第8和第9位用于设置中断触发模式为LEVEL还是PULSE
Pulse模式的意思是当FIFO中的数据量刚达到你要求的时候就会产生中断. 但是注意,该中断只授那一刻产生,如果那时候你正在处理上一次的中断而把该中断mask掉,那么该中断就会被丢掉,FIFO中数据就会一直增加直到溢出;
Level模式的意思是只要FIFO中的数据量达到你要求的时候就会产生中断,包括比你要求的多的时候.
对于串口接收数据丢失的情况,一般我们设置FIFO接收中断的触发阀值为0,中断触发方式为LEVEL;即当FIFO中的值大于或者等于0个,都会触发接收中断,从而让中断服务线程及时的接收走数据。此外,为了更及时的响应中断,我们可以将中断服务线程中的InterruptDone函数改成自己写入清中断标志和使能中断代替,提高中断效率。