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

📄 pxa27x_camera.c

📁 Windows CE 6.0 针对PXA270的开发板的BSP参考代码
💻 C
📖 第 1 页 / 共 5 页
字号:
int GenerateDMAChain(
    DESCRIPTOR_INFO_T *pDescriptorInfo,
    int fifo0_transfer_size,
    int fifo1_transfer_size,
    int fifo2_transfer_size
    )
{
    XLLP_DMAC_DESCRIPTOR_T *cur_des_virtual;
    int des_transfer_size, remain_size;
    unsigned int i,j,k,l;
    unsigned int fifo0_num_descriptors = 0;
    unsigned int fifo1_num_descriptors = 0;
    unsigned int fifo2_num_descriptors = 0;

    // calculate how many descriptors are needed per frame
    fifo0_num_descriptors = (( fifo0_transfer_size + SINGLE_DESCRIPTOR_TRANSFER_MAX -1 )
                            / SINGLE_DESCRIPTOR_TRANSFER_MAX) * 2;
    fifo1_num_descriptors = (( fifo1_transfer_size + SINGLE_DESCRIPTOR_TRANSFER_MAX -1 )
                            / SINGLE_DESCRIPTOR_TRANSFER_MAX) * 2;
    fifo2_num_descriptors = (( fifo2_transfer_size + SINGLE_DESCRIPTOR_TRANSFER_MAX -1 )
                            / SINGLE_DESCRIPTOR_TRANSFER_MAX) * 2;

    cur_des_virtual = (XLLP_DMAC_DESCRIPTOR_T*)pDescriptorInfo->pDescriptorBufferVirtAddress;

    // First iteration, build the real chain.
    // Second iteration, build the phantom chain.
    k = 0;
    l = 0;
    for(i=0; i < 2; i++) {
    
        remain_size = fifo0_transfer_size;

        for(j=0; j < fifo0_num_descriptors >> 1; j++) {
            // set descriptor
            if (remain_size > SINGLE_DESCRIPTOR_TRANSFER_MAX) 
                des_transfer_size = SINGLE_DESCRIPTOR_TRANSFER_MAX;
            else
                des_transfer_size = remain_size;

            // Build the primary DMA chain
            if (i == 0)
            {
                    cur_des_virtual->DDADR = (unsigned)pDescriptorInfo->pDescriptorBufferPhyAddress[++l];
                    cur_des_virtual->DSADR = XLLP_CI_REGBASE_PHY + XLLP_CIBR0;                      // FIFO0 physical address
                    cur_des_virtual->DTADR = (unsigned)pDescriptorInfo->pBufferPhyAddress[k++];
                    cur_des_virtual->DCMD = des_transfer_size | XLLP_DMAC_DCMD_FLOW_SRC | XLLP_DMAC_DCMD_INC_TRG_ADDR | (XLLP_DMAC_BURSTSIZE_16 << 16);
        
                    if (j == 0)
                    {
                            pDescriptorInfo->pPhysAddr_X1_CH0 = (XLLP_UINT32_T)pDescriptorInfo->pDescriptorBufferPhyAddress[l-1];// Physical address of the first real descriptor
                    }
                    // Special case for the last non-phantom descriptor in the chain
                    // Enable an end of frame interrupt for this descriptor only.
                    // Save a pointer to this descriptor and reset the remaining size for the phantom descriptor chain
                    if (j == ((fifo0_num_descriptors >> 1) - 1))
                    {
                            cur_des_virtual->DCMD |= XLLP_DMAC_DCMD_END_IRQ_EN;
                            pDescriptorInfo->pVirtAddr_Xn_CH0 = (XLLP_UINT32_T)cur_des_virtual;// Virtual address of the last real descriptor
                            // Reset the DMA transfer size for the phantom descriptor
                            remain_size = fifo0_transfer_size;
                    }
            } else
            // Build the phantom DMA chain
            {
                    cur_des_virtual->DDADR = (unsigned)pDescriptorInfo->pDescriptorBufferPhyAddress[++l];
                    cur_des_virtual->DSADR = XLLP_CI_REGBASE_PHY + XLLP_CIBR0;                      // FIFO0 physical address
                    cur_des_virtual->DTADR = (unsigned)pDescriptorInfo->pPhysAddr_Phantom;
                    cur_des_virtual->DCMD = des_transfer_size | XLLP_DMAC_DCMD_FLOW_SRC | XLLP_DMAC_DCMD_INC_TRG_ADDR | (XLLP_DMAC_BURSTSIZE_16 << 16);
            
                    if (j == 0)
                    {
                            pDescriptorInfo->pPhysAddr_XP1_CH0 = (XLLP_UINT32_T)pDescriptorInfo->pDescriptorBufferPhyAddress[l-1];          // Physical address of the first phantom descriptor
                    }
                    if (j == ((fifo0_num_descriptors >> 1) - 1))
                    {
                            pDescriptorInfo->pVirtAddr_XPn_CH0 = (XLLP_UINT32_T)cur_des_virtual;    // Virtual address of the last phantom descriptor       
                    }
            }
            // advance pointers
            remain_size -= des_transfer_size;
            cur_des_virtual++;
        }
    }
    
    // generate fifo1 dma chains
    if (fifo1_transfer_size) {

        for(i=0; i < 2; i++) {
            // in each iteration, generate one dma chain for one frame
            remain_size = fifo1_transfer_size;
        
            for(j=0; j < fifo1_num_descriptors >> 1; j++) {
                // set descriptor
                if (remain_size > SINGLE_DESCRIPTOR_TRANSFER_MAX) 
                    des_transfer_size = SINGLE_DESCRIPTOR_TRANSFER_MAX;
                else
                    des_transfer_size = remain_size;

                if (i == 0)
                {
                        cur_des_virtual->DDADR = (unsigned)pDescriptorInfo->pDescriptorBufferPhyAddress[++l];
                        cur_des_virtual->DSADR = XLLP_CI_REGBASE_PHY + XLLP_CIBR1;      // FIFO1 physical address
                        cur_des_virtual->DTADR = (unsigned)pDescriptorInfo->pBufferPhyAddress[k++];
                        cur_des_virtual->DCMD = des_transfer_size | XLLP_DMAC_DCMD_FLOW_SRC | XLLP_DMAC_DCMD_INC_TRG_ADDR | (XLLP_DMAC_BURSTSIZE_8 << 16);
                
                        if (j == 0)
                                pDescriptorInfo->pPhysAddr_X1_CH1 = (XLLP_UINT32_T)pDescriptorInfo->pDescriptorBufferPhyAddress[l-1];// Physical address of the first real descriptor
                        if (j == ((fifo1_num_descriptors >> 1) - 1))
                        {
                                pDescriptorInfo->pVirtAddr_Xn_CH1 = (XLLP_UINT32_T)cur_des_virtual;// Virtual address of the last real descriptor
        
                                // Reset the DMA transfer size for the phantom descriptor
                                remain_size = fifo1_transfer_size;
                        }
                }
                else 
                {
                        cur_des_virtual->DDADR = (unsigned)pDescriptorInfo->pDescriptorBufferPhyAddress[++l];
                        cur_des_virtual->DSADR = XLLP_CI_REGBASE_PHY + XLLP_CIBR1;      // FIFO1 physical address
                        cur_des_virtual->DTADR = (unsigned)pDescriptorInfo->pPhysAddr_Phantom;
                        cur_des_virtual->DCMD = des_transfer_size | XLLP_DMAC_DCMD_FLOW_SRC | XLLP_DMAC_DCMD_INC_TRG_ADDR | (XLLP_DMAC_BURSTSIZE_8 << 16);
                        
                        if (j == 0)
                                pDescriptorInfo->pPhysAddr_XP1_CH1 = (XLLP_UINT32_T)pDescriptorInfo->pDescriptorBufferPhyAddress[l-1];          // Physical address of the first phantom descriptor
                        if (j == ((fifo1_num_descriptors >> 1) - 1))
                                pDescriptorInfo->pVirtAddr_XPn_CH1 = (XLLP_UINT32_T)cur_des_virtual;    // Virtual address of the last phantom descriptor       
                }

                // advance pointers
                remain_size -= des_transfer_size;
                cur_des_virtual++;
            }
        }
    }

    // generate fifo2 dma chains
    if (fifo2_transfer_size) {

        for(i=0; i < 2; i++) {
            // in each iteration, generate one dma chain for one frame
            remain_size = fifo2_transfer_size;
    
            for(j=0; j < fifo2_num_descriptors >> 1; j++) {
                // set descriptor
                if (remain_size > SINGLE_DESCRIPTOR_TRANSFER_MAX) 
                    des_transfer_size = SINGLE_DESCRIPTOR_TRANSFER_MAX;
                else
                    des_transfer_size = remain_size;

                if (i == 0)
                {
                        cur_des_virtual->DDADR = (unsigned)pDescriptorInfo->pDescriptorBufferPhyAddress[++l];
                        cur_des_virtual->DSADR = XLLP_CI_REGBASE_PHY + XLLP_CIBR2;      // FIFO2 physical address
                        cur_des_virtual->DTADR = (unsigned)pDescriptorInfo->pBufferPhyAddress[k++];
                        cur_des_virtual->DCMD = des_transfer_size | XLLP_DMAC_DCMD_FLOW_SRC | XLLP_DMAC_DCMD_INC_TRG_ADDR | (XLLP_DMAC_BURSTSIZE_8 << 16);
        
                        if (j == 0)
                                pDescriptorInfo->pPhysAddr_X1_CH2 = (XLLP_UINT32_T)pDescriptorInfo->pDescriptorBufferPhyAddress[l-1];// Physical address of the first real descriptor
                        if (j == ((fifo2_num_descriptors >> 1) - 1))
                        {
                                pDescriptorInfo->pVirtAddr_Xn_CH2 = (XLLP_UINT32_T)cur_des_virtual;// Virtual address of the last real descriptor
        
                                // Reset the DMA transfer size for the phantom descriptor
                                remain_size = fifo2_transfer_size;
                        }
        
                }
                else
                {
                        cur_des_virtual->DDADR = (unsigned)pDescriptorInfo->pDescriptorBufferPhyAddress[++l];
                        cur_des_virtual->DSADR = XLLP_CI_REGBASE_PHY + XLLP_CIBR2;      // FIFO2 physical address
                        cur_des_virtual->DTADR = (unsigned)pDescriptorInfo->pPhysAddr_Phantom;
                        cur_des_virtual->DCMD = des_transfer_size | XLLP_DMAC_DCMD_FLOW_SRC | XLLP_DMAC_DCMD_INC_TRG_ADDR | (XLLP_DMAC_BURSTSIZE_8 << 16);
            
                        if (j == 0)
                                pDescriptorInfo->pPhysAddr_XP1_CH2 = (XLLP_UINT32_T)pDescriptorInfo->pDescriptorBufferPhyAddress[l-1];          // Physical address of the first phantom descriptor
                        if (j == ((fifo2_num_descriptors >> 1) - 1))
                                pDescriptorInfo->pVirtAddr_XPn_CH2 = (XLLP_UINT32_T)cur_des_virtual;    // Virtual address of the last phantom descriptor       
        
                }
                // advance pointers
                remain_size -= des_transfer_size;
                cur_des_virtual++;
            }
        }
    }
    return TRUE;   
}


/***********************************************************************
 *
 * Private functions
 *
 ***********************************************************************/
void PrvStartDMATransfer(P_HW_CONTEXT_T pHwContext, unsigned block_id)
{
    XLLP_DMAC_DESCRIPTOR_T *des_virtual, *des_physical;


    des_virtual = (P_XLLP_DMAC_DESCRIPTOR_T)NULL;
    des_physical = (P_XLLP_DMAC_DESCRIPTOR_T)pHwContext->XllpDMA.fifo0_descriptors_physical;
    XllpDmacCfgChannelDescTransfer( //des_virtual,
                               des_physical,
                               pHwContext->XllpDMA.dma_channels[0],        
                               CAMERA_DMA_DEVICE[0],                    
                               XLLP_DMAC_ALIGNMENT_OFF              
                              );

    if ( pHwContext->XllpDMA.fifo1_transfer_size ) {
                des_virtual = (P_XLLP_DMAC_DESCRIPTOR_T)NULL;
                des_physical = (P_XLLP_DMAC_DESCRIPTOR_T)pHwContext->XllpDMA.fifo1_descriptors_physical;
                XllpDmacCfgChannelDescTransfer( //des_virtual,
                                   des_physical,
                                   pHwContext->XllpDMA.dma_channels[1],        
                                   CAMERA_DMA_DEVICE[1],                    
                                   XLLP_DMAC_ALIGNMENT_OFF              
                                  );
        }

    if ( pHwContext->XllpDMA.fifo2_transfer_size ) {
        des_virtual = (P_XLLP_DMAC_DESCRIPTOR_T)NULL;
        des_physical = (P_XLLP_DMAC_DESCRIPTOR_T)pHwContext->XllpDMA.fifo2_descriptors_physical;
        XllpDmacCfgChannelDescTransfer( //des_virtual,
                                   des_physical,
                                   pHwContext->XllpDMA.dma_channels[2],        
                                   CAMERA_DMA_DEVICE[2],                    
                                   XLLP_DMAC_ALIGNMENT_OFF              
                                  );
    }

    if ( pHwContext->XllpDMA.fifo0_transfer_size &&
         pHwContext->XllpDMA.fifo1_transfer_size &&
         pHwContext->XllpDMA.fifo2_transfer_size ) 
    {
        XllpDmacStartTransfer( pHwContext->XllpDMA.dma_channels[0] );
        XllpDmacStartTransfer( pHwContext->XllpDMA.dma_channels[1] );
        XllpDmacStartTransfer( pHwContext->XllpDMA.dma_channels[2] );
    } else 
    {
        XllpDmacStartTransfer( pHwContext->XllpDMA.dma_channels[0] );
    }

}

void PrvStopDMATransfer(P_HW_CONTEXT_T pHwContext)
{
    unsigned int capture_output_format = pHwContext->XllpCAMERA.Video_capture_output_format;
    if (pHwContext->XllpCAMERA.capture_mode == XLLP_CAMERA_MODE_STILL)
    {
       capture_output_format = pHwContext->XllpCAMERA.Still_capture_output_format;
    }

    // stop channel 0
    XllpDmacStopTransfer( pHwContext->XllpDMA.dma_channels[0] );

    // stop channel 1 and 2  
    if ( capture_output_format == XLLP_CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR ) 
    {
        XllpDmacStopTransfer( pHwContext->XllpDMA.dma_channels[1] );
        XllpDmacStopTransfer( pHwContext->XllpDMA.dma_channels[2] );
    }
}

XLLP_STATUS_T PrvStartCapture(P_HW_CONTEXT_T pHwContext, unsigned int block_id, unsigned int frames)
{
    XLLP_STATUS_T   status;
    
    // clear ci fifo
    XllpCIResetFIFO(pHwContext->XllpCAMERA.ci_reg_base);
    XllpCIClearInterruptStatus(pHwContext->XllpCAMERA.ci_reg_base, 0xFFFFFFFF);

    // start dma
    PrvStartDMATransfer(pHwContext, block_id);

    // start capture
    status = pHwContext->XllpCAMERA.camera_functions->start_capture(&pHwContext->XllpCAMERA, frames);    
    return status;
}


// Set the image format
XLLP_STATUS_T PrvSetDMARingBuffer(P_HW_CONTEXT_T pHwContext)
{
    unsigned int frame_size;
    unsigned int capture_output_format = pHwContext->XllpCAMERA.Video_capture_output_format;
    if (pHwContext->XllpCAMERA.capture_mode == XLLP_CAMERA_MODE_STILL)
    {
       capture_output_format = pHwContext->XllpCAMERA.Still_capture_output_format;
    }

    // ring buffer init
    switch(capture_output_format) {
        case XLLP_CAMERA_IMAGE_FORMAT_RGB555:
        case XLLP_CAMERA_IMAGE_FORMAT_RGB565:
            frame_size = pHwContext->XllpCAMERA.capture_width * pHwContext->XllpCAMERA.capture_height * 2;
            pHwContext->XllpDMA.fifo0_transfer_size = frame_size;
            pHwContext->XllpDMA.fifo1_transfer_size = 0;
            pHwContext->XllpDMA.fifo2_transfer_size = 0;
            break;
        case XLLP_CAMERA_IMAGE_FORMAT_YCBCR422_PACKED:
            frame_size = pHwContext->XllpCAMERA.capture_width * pHwContext->XllpCAMERA.capture_height * 2;
            pHwContext->XllpDMA.fifo0_transfer_size = frame_size;
            pHwContext->XllpDMA.fifo1_transfer_size = 0;
            pHwContext->XllpDMA.fifo2_transfer_size = 0;
            break;
        case XLLP_CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR:
            frame_size = pHwContext->XllpCAMERA.capture_width * pHwContext->XllpCAMERA.capture_height * 2;
            pHwContext->XllpDMA.fifo0_transfer_size = frame_size / 2;
            pHwContext->XllpDMA.fifo1_transfer_size = frame_size / 4;
            pHwContext->Xl

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -