File indexing completed on 2025-05-11 08:22:58
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "fsl_csi.h"
0010 #if CSI_DRIVER_FRAG_MODE
0011 #include "fsl_cache.h"
0012 #endif
0013
0014 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
0015 #include "fsl_memory.h"
0016 #endif
0017
0018
0019
0020
0021
0022 #if (!defined(CSI_CR3_TWO_8BIT_SENSOR_MASK) && defined(CSI_CR3_SENSOR_16BITS_MASK))
0023 #define CSI_CR3_TWO_8BIT_SENSOR_MASK CSI_CR3_SENSOR_16BITS_MASK
0024 #endif
0025
0026
0027 #ifndef FSL_COMPONENT_ID
0028 #define FSL_COMPONENT_ID "platform.drivers.csi"
0029 #endif
0030
0031
0032 #define CSI_MAX_ACTIVE_FRAME_NUM 2U
0033
0034
0035 #define CSI_FRAG_INPUT_BYTES_PER_PIXEL 2U
0036
0037 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
0038 #define CSI_ADDR_CPU_2_IP(addr) (MEMORY_ConvertMemoryMapAddress((uint32_t)(addr), kMEMORY_Local2DMA))
0039 #define CSI_ADDR_IP_2_CPU(addr) (MEMORY_ConvertMemoryMapAddress((uint32_t)(addr), kMEMORY_DMA2Local))
0040 #else
0041 #define CSI_ADDR_CPU_2_IP(addr) (addr)
0042 #define CSI_ADDR_IP_2_CPU(addr) (addr)
0043 #endif
0044
0045
0046
0047
0048 typedef union pvoid_to_u32
0049 {
0050 void *pvoid;
0051 uint32_t u32;
0052 } pvoid_to_u32_t;
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 static uint32_t CSI_GetInstance(CSI_Type *base);
0066
0067 #if !CSI_DRIVER_FRAG_MODE
0068
0069
0070
0071
0072
0073
0074
0075
0076 static uint8_t CSI_TransferGetQueueDelta(uint8_t startIdx, uint8_t endIdx);
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088 static uint8_t CSI_TransferIncreaseQueueIdx(uint8_t idx);
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 static uint32_t CSI_TransferGetEmptyBufferCount(csi_handle_t *handle);
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 static uint32_t CSI_TransferGetEmptyBuffer(csi_handle_t *handle);
0110
0111
0112
0113
0114
0115
0116
0117 static void CSI_TransferPutEmptyBuffer(csi_handle_t *handle, uint32_t buffer);
0118
0119
0120
0121
0122
0123
0124
0125
0126 static uint32_t CSI_GetRxBufferAddr(CSI_Type *base, uint8_t index);
0127
0128
0129 typedef void (*csi_isr_t)(CSI_Type *base, csi_handle_t *handle);
0130
0131 #else
0132
0133
0134 typedef void (*csi_isr_t)(CSI_Type *base, csi_frag_handle_t *handle);
0135 #endif
0136
0137
0138
0139
0140
0141 static CSI_Type *const s_csiBases[] = CSI_BASE_PTRS;
0142
0143 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0144
0145 static const clock_ip_name_t s_csiClocks[] = CSI_CLOCKS;
0146 #endif
0147
0148
0149 #if !CSI_DRIVER_FRAG_MODE
0150 static csi_handle_t *s_csiHandle[ARRAY_SIZE(s_csiBases)];
0151 #else
0152 static csi_frag_handle_t *s_csiHandle[ARRAY_SIZE(s_csiBases)];
0153 #endif
0154
0155
0156 static const IRQn_Type s_csiIRQ[] = CSI_IRQS;
0157
0158
0159 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
0160 static csi_isr_t s_csiIsr = (csi_isr_t)DefaultISR;
0161 #else
0162 static csi_isr_t s_csiIsr;
0163 #endif
0164
0165
0166
0167
0168 static uint32_t CSI_GetInstance(CSI_Type *base)
0169 {
0170 uint32_t instance;
0171
0172
0173 for (instance = 0; instance < ARRAY_SIZE(s_csiBases); instance++)
0174 {
0175 if (s_csiBases[instance] == base)
0176 {
0177 break;
0178 }
0179 }
0180
0181 assert(instance < ARRAY_SIZE(s_csiBases));
0182
0183 return instance;
0184 }
0185
0186 #if !CSI_DRIVER_FRAG_MODE
0187 static uint8_t CSI_TransferGetQueueDelta(uint8_t startIdx, uint8_t endIdx)
0188 {
0189 uint8_t ret;
0190
0191 if (endIdx >= startIdx)
0192 {
0193 ret = endIdx - startIdx;
0194 }
0195 else
0196 {
0197 ret = (uint8_t)(endIdx + CSI_DRIVER_ACTUAL_QUEUE_SIZE - startIdx);
0198 }
0199
0200 return ret;
0201 }
0202
0203 static uint8_t CSI_TransferIncreaseQueueIdx(uint8_t idx)
0204 {
0205 uint8_t ret;
0206
0207
0208
0209
0210
0211
0212
0213
0214 ret = idx + 1U;
0215
0216 if (ret >= CSI_DRIVER_ACTUAL_QUEUE_SIZE)
0217 {
0218 ret = 0U;
0219 }
0220
0221 return ret;
0222 }
0223
0224 static uint32_t CSI_TransferGetEmptyBufferCount(csi_handle_t *handle)
0225 {
0226 return handle->emptyBufferCnt;
0227 }
0228
0229 static uint32_t CSI_TransferGetEmptyBuffer(csi_handle_t *handle)
0230 {
0231 pvoid_to_u32_t buf;
0232
0233 buf.pvoid = handle->emptyBuffer;
0234 handle->emptyBufferCnt--;
0235 handle->emptyBuffer = *(void **)(buf.pvoid);
0236
0237 return buf.u32;
0238 }
0239
0240 static void CSI_TransferPutEmptyBuffer(csi_handle_t *handle, uint32_t buffer)
0241 {
0242 pvoid_to_u32_t buf;
0243 buf.u32 = buffer;
0244
0245 *(void **)(buf.pvoid) = handle->emptyBuffer;
0246 handle->emptyBuffer = buf.pvoid;
0247 handle->emptyBufferCnt++;
0248 }
0249
0250 static uint32_t CSI_GetRxBufferAddr(CSI_Type *base, uint8_t index)
0251 {
0252 uint32_t addr;
0253
0254 if (index != 0U)
0255 {
0256 addr = CSI_REG_DMASA_FB2(base);
0257 }
0258 else
0259 {
0260 addr = CSI_REG_DMASA_FB1(base);
0261 }
0262
0263 return CSI_ADDR_IP_2_CPU(addr);
0264 }
0265
0266 #endif
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279 status_t CSI_Init(CSI_Type *base, const csi_config_t *config)
0280 {
0281 assert(NULL != config);
0282 uint32_t reg;
0283 uint32_t imgWidth_Bytes;
0284 uint8_t busCyclePerPixel;
0285
0286 imgWidth_Bytes = (uint32_t)config->width * (uint32_t)config->bytesPerPixel;
0287
0288
0289 if ((0U != (imgWidth_Bytes & 0x07U)) || (0U != ((uint32_t)config->linePitch_Bytes & 0x07U)))
0290 {
0291 return kStatus_InvalidArgument;
0292 }
0293
0294 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0295 uint32_t instance = CSI_GetInstance(base);
0296 CLOCK_EnableClock(s_csiClocks[instance]);
0297 #endif
0298
0299 CSI_Reset(base);
0300
0301
0302 reg = ((uint32_t)config->workMode) | config->polarityFlags | CSI_CR1_FCC_MASK;
0303
0304 if (config->useExtVsync)
0305 {
0306 reg |= CSI_CR1_EXT_VSYNC_MASK;
0307 }
0308
0309 CSI_REG_CR1(base) = reg;
0310
0311
0312
0313
0314
0315
0316 if ((kCSI_DataBus8Bit == config->dataBus) && (2U == config->bytesPerPixel))
0317 {
0318 busCyclePerPixel = 2U;
0319 }
0320 else
0321 {
0322 busCyclePerPixel = 1U;
0323 }
0324
0325 if (4U == config->bytesPerPixel)
0326 {
0327 CSI_REG_CR18(base) |= CSI_CR18_PARALLEL24_EN_MASK;
0328 }
0329
0330 if (kCSI_DataBus16Bit == config->dataBus)
0331 {
0332 CSI_REG_CR3(base) |= CSI_CR3_TWO_8BIT_SENSOR_MASK;
0333 }
0334
0335
0336 CSI_REG_IMAG_PARA(base) =
0337 (((uint32_t)config->width * (uint32_t)busCyclePerPixel) << CSI_IMAG_PARA_IMAGE_WIDTH_SHIFT) |
0338 ((uint32_t)(config->height) << CSI_IMAG_PARA_IMAGE_HEIGHT_SHIFT);
0339
0340
0341 CSI_REG_FBUF_PARA(base) = (uint32_t)((config->linePitch_Bytes - imgWidth_Bytes) / 8U)
0342 << CSI_FBUF_PARA_FBUF_STRIDE_SHIFT;
0343
0344
0345 CSI_REG_CR3(base) |= CSI_CR3_ECC_AUTO_EN_MASK;
0346
0347
0348
0349
0350
0351
0352 if (0U == (imgWidth_Bytes % (8U * 16U)))
0353 {
0354 CSI_REG_CR2(base) = CSI_CR2_DMA_BURST_TYPE_RFF(3U);
0355 CSI_REG_CR3(base) = (CSI_REG_CR3(base) & ~CSI_CR3_RxFF_LEVEL_MASK) | ((2U << CSI_CR3_RxFF_LEVEL_SHIFT));
0356 }
0357 else if (0U == (imgWidth_Bytes % (8U * 8U)))
0358 {
0359 CSI_REG_CR2(base) = CSI_CR2_DMA_BURST_TYPE_RFF(2U);
0360 CSI_REG_CR3(base) = (CSI_REG_CR3(base) & ~CSI_CR3_RxFF_LEVEL_MASK) | ((1U << CSI_CR3_RxFF_LEVEL_SHIFT));
0361 }
0362 else
0363 {
0364 CSI_REG_CR2(base) = CSI_CR2_DMA_BURST_TYPE_RFF(1U);
0365 CSI_REG_CR3(base) = (CSI_REG_CR3(base) & ~CSI_CR3_RxFF_LEVEL_MASK) | ((0U << CSI_CR3_RxFF_LEVEL_SHIFT));
0366 }
0367
0368 CSI_ReflashFifoDma(base, kCSI_RxFifo);
0369
0370 return kStatus_Success;
0371 }
0372
0373
0374
0375
0376
0377
0378
0379
0380 void CSI_Deinit(CSI_Type *base)
0381 {
0382
0383 CSI_Stop(base);
0384 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0385 uint32_t instance = CSI_GetInstance(base);
0386 CLOCK_DisableClock(s_csiClocks[instance]);
0387 #endif
0388 }
0389
0390
0391
0392
0393
0394
0395
0396
0397 void CSI_Reset(CSI_Type *base)
0398 {
0399 uint32_t csisr;
0400
0401
0402 CSI_Stop(base);
0403
0404
0405 CSI_REG_CR3(base) = 0U;
0406
0407
0408 CSI_REG_CR3(base) |= CSI_CR3_FRMCNT_RST_MASK;
0409 while (0U != (CSI_REG_CR3(base) & CSI_CR3_FRMCNT_RST_MASK))
0410 {
0411 }
0412
0413
0414 CSI_ClearFifo(base, kCSI_AllFifo);
0415
0416
0417 CSI_ReflashFifoDma(base, kCSI_AllFifo);
0418
0419
0420 csisr = CSI_REG_SR(base);
0421 CSI_REG_SR(base) = csisr;
0422
0423
0424 CSI_REG_CR1(base) = CSI_CR1_HSYNC_POL_MASK | CSI_CR1_EXT_VSYNC_MASK;
0425 CSI_REG_CR2(base) = 0U;
0426 CSI_REG_CR3(base) = 0U;
0427 #if defined(CSI_CR18_CSI_LCDIF_BUFFER_LINES)
0428 CSI_REG_CR18(base) = CSI_CR18_AHB_HPROT(0x0DU) | CSI_CR18_CSI_LCDIF_BUFFER_LINES(0x02U);
0429 #else
0430 CSI_REG_CR18(base) = CSI_CR18_AHB_HPROT(0x0DU);
0431 #endif
0432 CSI_REG_FBUF_PARA(base) = 0U;
0433 CSI_REG_IMAG_PARA(base) = 0U;
0434 }
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454 void CSI_GetDefaultConfig(csi_config_t *config)
0455 {
0456 assert(NULL != config);
0457
0458
0459 (void)memset(config, 0, sizeof(*config));
0460
0461 config->width = 320U;
0462 config->height = 240U;
0463 config->polarityFlags = (uint32_t)kCSI_HsyncActiveHigh | (uint32_t)kCSI_DataLatchOnRisingEdge;
0464 config->bytesPerPixel = 2U;
0465 config->linePitch_Bytes = 320U * 2U;
0466 config->workMode = kCSI_GatedClockMode;
0467 config->dataBus = kCSI_DataBus8Bit;
0468 config->useExtVsync = true;
0469 }
0470
0471
0472
0473
0474
0475
0476
0477
0478 void CSI_SetRxBufferAddr(CSI_Type *base, uint8_t index, uint32_t addr)
0479 {
0480 addr = CSI_ADDR_CPU_2_IP(addr);
0481
0482 if (0U != index)
0483 {
0484 CSI_REG_DMASA_FB2(base) = addr;
0485 }
0486 else
0487 {
0488 CSI_REG_DMASA_FB1(base) = addr;
0489 }
0490 }
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500 void CSI_ClearFifo(CSI_Type *base, csi_fifo_t fifo)
0501 {
0502 uint32_t cr1;
0503 uint32_t mask = 0U;
0504
0505
0506 cr1 = CSI_REG_CR1(base);
0507 CSI_REG_CR1(base) = (cr1 & ~CSI_CR1_FCC_MASK);
0508
0509 if (0U != ((uint32_t)fifo & (uint32_t)kCSI_RxFifo))
0510 {
0511 mask |= CSI_CR1_CLR_RXFIFO_MASK;
0512 }
0513
0514 if (0U != ((uint32_t)fifo & (uint32_t)kCSI_StatFifo))
0515 {
0516 mask |= CSI_CR1_CLR_STATFIFO_MASK;
0517 }
0518
0519 CSI_REG_CR1(base) = (cr1 & ~CSI_CR1_FCC_MASK) | mask;
0520
0521
0522 while (0U != (CSI_REG_CR1(base) & mask))
0523 {
0524 }
0525
0526
0527 CSI_REG_CR1(base) = cr1;
0528 }
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543 void CSI_ReflashFifoDma(CSI_Type *base, csi_fifo_t fifo)
0544 {
0545 uint32_t cr3 = 0U;
0546
0547 if (0U != ((uint32_t)fifo & (uint32_t)kCSI_RxFifo))
0548 {
0549 cr3 |= CSI_CR3_DMA_REFLASH_RFF_MASK;
0550 }
0551
0552 if (0U != ((uint32_t)fifo & (uint32_t)kCSI_StatFifo))
0553 {
0554 cr3 |= CSI_CR3_DMA_REFLASH_SFF_MASK;
0555 }
0556
0557 CSI_REG_CR3(base) |= cr3;
0558
0559
0560 while (0U != (CSI_REG_CR3(base) & cr3))
0561 {
0562 }
0563 }
0564
0565
0566
0567
0568
0569
0570
0571
0572 void CSI_EnableFifoDmaRequest(CSI_Type *base, csi_fifo_t fifo, bool enable)
0573 {
0574 uint32_t cr3 = 0U;
0575
0576 if (0U != ((uint32_t)fifo & (uint32_t)kCSI_RxFifo))
0577 {
0578 cr3 |= CSI_CR3_DMA_REQ_EN_RFF_MASK;
0579 }
0580
0581 if (0U != ((uint32_t)fifo & (uint32_t)kCSI_StatFifo))
0582 {
0583 cr3 |= CSI_CR3_DMA_REQ_EN_SFF_MASK;
0584 }
0585
0586 if (enable)
0587 {
0588 CSI_REG_CR3(base) |= cr3;
0589 }
0590 else
0591 {
0592 CSI_REG_CR3(base) &= ~cr3;
0593 }
0594 }
0595
0596
0597
0598
0599
0600
0601
0602 void CSI_EnableInterrupts(CSI_Type *base, uint32_t mask)
0603 {
0604 CSI_REG_CR1(base) |= (mask & CSI_CR1_INT_EN_MASK);
0605 CSI_REG_CR3(base) |= (mask & CSI_CR3_INT_EN_MASK);
0606 CSI_REG_CR18(base) |= ((mask & CSI_CR18_INT_EN_MASK) >> 6U);
0607 }
0608
0609
0610
0611
0612
0613
0614
0615 void CSI_DisableInterrupts(CSI_Type *base, uint32_t mask)
0616 {
0617 CSI_REG_CR1(base) &= ~(mask & CSI_CR1_INT_EN_MASK);
0618 CSI_REG_CR3(base) &= ~(mask & CSI_CR3_INT_EN_MASK);
0619 CSI_REG_CR18(base) &= ~((mask & CSI_CR18_INT_EN_MASK) >> 6U);
0620 }
0621
0622 #if !CSI_DRIVER_FRAG_MODE
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636 status_t CSI_TransferCreateHandle(CSI_Type *base,
0637 csi_handle_t *handle,
0638 csi_transfer_callback_t callback,
0639 void *userData)
0640 {
0641 assert(NULL != handle);
0642 uint32_t instance;
0643
0644 (void)memset(handle, 0, sizeof(*handle));
0645
0646
0647 handle->callback = callback;
0648 handle->userData = userData;
0649
0650
0651 instance = CSI_GetInstance(base);
0652
0653
0654 s_csiHandle[instance] = handle;
0655
0656 s_csiIsr = CSI_TransferHandleIRQ;
0657
0658
0659 (void)EnableIRQ(s_csiIRQ[instance]);
0660
0661 return kStatus_Success;
0662 }
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678 status_t CSI_TransferStart(CSI_Type *base, csi_handle_t *handle)
0679 {
0680 assert(NULL != handle);
0681
0682 uint32_t emptyBufferCount;
0683
0684 emptyBufferCount = CSI_TransferGetEmptyBufferCount(handle);
0685
0686 if (emptyBufferCount < 2U)
0687 {
0688 return kStatus_CSI_NoEmptyBuffer;
0689 }
0690
0691
0692
0693
0694
0695
0696 CSI_REG_CR18(base) = (CSI_REG_CR18(base) & ~CSI_CR18_MASK_OPTION_MASK) | CSI_CR18_MASK_OPTION(0) |
0697 CSI_CR18_BASEADDR_SWITCH_SEL_MASK | CSI_CR18_BASEADDR_SWITCH_EN_MASK;
0698
0699
0700 CSI_REG_DMASA_FB1(base) = CSI_ADDR_CPU_2_IP(CSI_TransferGetEmptyBuffer(handle));
0701 CSI_REG_DMASA_FB2(base) = CSI_ADDR_CPU_2_IP(CSI_TransferGetEmptyBuffer(handle));
0702
0703 handle->activeBufferNum = CSI_MAX_ACTIVE_FRAME_NUM;
0704
0705
0706 CSI_ReflashFifoDma(base, kCSI_RxFifo);
0707
0708 handle->transferStarted = true;
0709
0710 CSI_EnableInterrupts(
0711 base, (uint32_t)kCSI_RxBuffer1DmaDoneInterruptEnable | (uint32_t)kCSI_RxBuffer0DmaDoneInterruptEnable);
0712
0713 CSI_Start(base);
0714
0715 return kStatus_Success;
0716 }
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729
0730 status_t CSI_TransferStop(CSI_Type *base, csi_handle_t *handle)
0731 {
0732 assert(NULL != handle);
0733 uint8_t activeBufferNum;
0734 uint8_t bufIdx;
0735
0736 CSI_Stop(base);
0737 CSI_DisableInterrupts(
0738 base, (uint32_t)kCSI_RxBuffer1DmaDoneInterruptEnable | (uint32_t)kCSI_RxBuffer0DmaDoneInterruptEnable);
0739
0740 activeBufferNum = handle->activeBufferNum;
0741
0742 handle->transferStarted = false;
0743 handle->activeBufferNum = 0;
0744
0745
0746
0747
0748
0749
0750
0751 for (bufIdx = 0; bufIdx < activeBufferNum; bufIdx++)
0752 {
0753 CSI_TransferPutEmptyBuffer(handle, CSI_GetRxBufferAddr(base, bufIdx));
0754 }
0755
0756 return kStatus_Success;
0757 }
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773 status_t CSI_TransferSubmitEmptyBuffer(CSI_Type *base, csi_handle_t *handle, uint32_t frameBuffer)
0774 {
0775 uint32_t csicr1;
0776
0777
0778 csicr1 = CSI_REG_CR1(base);
0779
0780 CSI_REG_CR1(base) = (csicr1 & ~(CSI_CR1_FB2_DMA_DONE_INTEN_MASK | CSI_CR1_FB1_DMA_DONE_INTEN_MASK));
0781
0782
0783 CSI_TransferPutEmptyBuffer(handle, frameBuffer);
0784
0785 CSI_REG_CR1(base) = csicr1;
0786
0787 return kStatus_Success;
0788 }
0789
0790
0791
0792
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802
0803
0804
0805 status_t CSI_TransferGetFullBuffer(CSI_Type *base, csi_handle_t *handle, uint32_t *frameBuffer)
0806 {
0807 uint32_t csicr1;
0808 status_t status;
0809 uint8_t queueReadIdx;
0810 uint8_t queueWriteIdx;
0811
0812 queueReadIdx = handle->queueReadIdx;
0813 queueWriteIdx = handle->queueWriteIdx;
0814
0815
0816 if (queueReadIdx == queueWriteIdx)
0817 {
0818 status = kStatus_CSI_NoFullBuffer;
0819 }
0820 else
0821 {
0822
0823 csicr1 = CSI_REG_CR1(base);
0824
0825 CSI_REG_CR1(base) = (csicr1 & ~(CSI_CR1_FB2_DMA_DONE_INTEN_MASK | CSI_CR1_FB1_DMA_DONE_INTEN_MASK));
0826
0827 *frameBuffer = handle->frameBufferQueue[handle->queueReadIdx];
0828
0829 handle->queueReadIdx = CSI_TransferIncreaseQueueIdx(handle->queueReadIdx);
0830
0831 CSI_REG_CR1(base) = csicr1;
0832
0833 status = kStatus_Success;
0834 }
0835
0836 return status;
0837 }
0838
0839
0840
0841
0842
0843
0844
0845
0846
0847
0848 void CSI_TransferHandleIRQ(CSI_Type *base, csi_handle_t *handle)
0849 {
0850 uint8_t queueWriteIdx;
0851 uint8_t queueReadIdx;
0852 uint8_t dmaDoneBufferIdx;
0853 uint32_t frameBuffer;
0854 uint32_t csisr = CSI_REG_SR(base);
0855
0856
0857 CSI_REG_SR(base) = csisr;
0858
0859
0860
0861
0862
0863 if ((csisr & (CSI_SR_DMA_TSF_DONE_FB2_MASK | CSI_SR_DMA_TSF_DONE_FB1_MASK)) ==
0864 (CSI_SR_DMA_TSF_DONE_FB2_MASK | CSI_SR_DMA_TSF_DONE_FB1_MASK))
0865 {
0866 ;
0867 }
0868 else if (0U != (csisr & (CSI_SR_DMA_TSF_DONE_FB2_MASK | CSI_SR_DMA_TSF_DONE_FB1_MASK)))
0869 {
0870 if (0U != (csisr & CSI_SR_DMA_TSF_DONE_FB2_MASK))
0871 {
0872 dmaDoneBufferIdx = 1;
0873 }
0874 else
0875 {
0876 dmaDoneBufferIdx = 0;
0877 }
0878
0879 if (handle->activeBufferNum == CSI_MAX_ACTIVE_FRAME_NUM)
0880 {
0881 queueWriteIdx = handle->queueWriteIdx;
0882 queueReadIdx = handle->queueReadIdx;
0883
0884 if (CSI_TransferGetQueueDelta(queueReadIdx, queueWriteIdx) < CSI_DRIVER_QUEUE_SIZE)
0885 {
0886
0887 frameBuffer = CSI_GetRxBufferAddr(base, dmaDoneBufferIdx);
0888 handle->frameBufferQueue[queueWriteIdx] = frameBuffer;
0889
0890 handle->queueWriteIdx = CSI_TransferIncreaseQueueIdx(queueWriteIdx);
0891
0892 handle->activeBufferNum--;
0893
0894 if (NULL != handle->callback)
0895 {
0896 handle->callback(base, handle, kStatus_CSI_FrameDone, handle->userData);
0897 }
0898 }
0899 else
0900 {
0901 }
0902 }
0903
0904
0905
0906
0907
0908
0909 if (handle->activeBufferNum < CSI_MAX_ACTIVE_FRAME_NUM)
0910 {
0911 if (CSI_TransferGetEmptyBufferCount(handle) > 0U)
0912 {
0913
0914 CSI_SetRxBufferAddr(base, dmaDoneBufferIdx, CSI_TransferGetEmptyBuffer(handle));
0915 handle->activeBufferNum++;
0916 }
0917 else
0918 {
0919
0920
0921
0922 frameBuffer = CSI_GetRxBufferAddr(base, dmaDoneBufferIdx ^ 1U);
0923 CSI_SetRxBufferAddr(base, dmaDoneBufferIdx, frameBuffer);
0924 }
0925 }
0926 }
0927 else
0928 {
0929 }
0930 }
0931
0932 #else
0933
0934 #if defined(__CC_ARM)
0935 __asm void CSI_ExtractYFromYUYV(void *datBase, const void *dmaBase, size_t count)
0936 {
0937
0938 push {r4-r7, lr}
0939 10
0940 LDMIA R1!, {r3-r6}
0941 bfi r7, r3, #0, #8
0942 bfi ip, r5, #0, #8
0943 lsr r3, r3, #16
0944 lsr r5, r5, #16
0945 bfi r7, r3, #8, #8
0946 bfi ip, r5, #8, #8
0947 bfi r7, r4, #16, #8
0948 bfi ip, r6, #16, #8
0949 lsr r4, r4, #16
0950 lsr r6, r6, #16
0951 bfi r7, r4, #24, #8
0952 bfi ip, r6, #24, #8
0953 STMIA r0!, {r7, ip}
0954 subs r2, #8
0955 bne %b10
0956 pop {r4-r7, pc}
0957
0958 }
0959
0960 __asm void CSI_ExtractYFromUYVY(void *datBase, const void *dmaBase, size_t count)
0961 {
0962
0963 push {r4-r7, lr}
0964 10
0965 LDMIA R1!, {r3-r6}
0966 lsr r3, r3, #8
0967 lsr r5, r5, #8
0968 bfi r7, r3, #0, #8
0969 bfi ip, r5, #0, #8
0970 lsr r3, r3, #16
0971 lsr r5, r5, #16
0972 bfi r7, r3, #8, #8
0973 bfi ip, r5, #8, #8
0974 lsr r4, r4, #8
0975 lsr r6, r6, #8
0976 bfi r7, r4, #16, #8
0977 bfi ip, r6, #16, #8
0978 lsr r4, r4, #16
0979 lsr r6, r6, #16
0980 bfi r7, r4, #24, #8
0981 bfi ip, r6, #24, #8
0982 STMIA r0!, {r7, ip}
0983 subs r2, #8
0984 bne %b10
0985 pop {r4-r7, pc}
0986
0987 }
0988
0989 #elif (defined(__GNUC__) || defined(__ICCARM__)) || defined(__ARMCC_VERSION)
0990 #if defined(__ICCARM__)
0991 #pragma diag_suppress = Pe940
0992 #endif
0993 __attribute__((naked)) void CSI_ExtractYFromYUYV(void *datBase, const void *dmaBase, size_t count);
0994 void CSI_ExtractYFromYUYV(void *datBase, const void *dmaBase, size_t count)
0995 {
0996
0997 __asm volatile(
0998 " push {r1-r7, r12, lr} \n"
0999 "loop0: \n"
1000 " ldmia r1!, {r3-r6} \n"
1001 " bfi r7, r3, #0, #8 \n"
1002 " bfi r12, r5, #0, #8 \n"
1003 " lsr r3, r3, #16 \n"
1004 " lsr r5, r5, #16 \n"
1005 " bfi r7, r3, #8, #8 \n"
1006 " bfi r12, r5, #8, #8 \n"
1007 " bfi r7, r4, #16, #8 \n"
1008 " bfi r12, r6, #16, #8 \n"
1009 " lsr r4, r4, #16 \n"
1010 " lsr r6, r6, #16 \n"
1011 " bfi r7, r4, #24, #8 \n"
1012 " bfi r12, r6, #24, #8 \n"
1013 " stmia r0!, {r7, r12} \n"
1014 " subs r2, #8 \n"
1015 " bne loop0 \n"
1016 " pop {r1-r7, r12, pc} \n");
1017
1018 }
1019
1020 __attribute__((naked)) void CSI_ExtractYFromUYVY(void *datBase, const void *dmaBase, size_t count);
1021 void CSI_ExtractYFromUYVY(void *datBase, const void *dmaBase, size_t count)
1022 {
1023
1024 __asm volatile(
1025 " push {r1-r7, r12, lr} \n"
1026 "loop1: \n"
1027 " ldmia r1!, {r3-r6} \n"
1028 " lsr r3, r3, #8 \n"
1029 " lsr r5, r5, #8 \n"
1030 " bfi r7, r3, #0, #8 \n"
1031 " bfi r12, r5, #0, #8 \n"
1032 " lsr r3, r3, #16 \n"
1033 " lsr r5, r5, #16 \n"
1034 " bfi r7, r3, #8, #8 \n"
1035 " bfi r12, r5, #8, #8 \n"
1036 " lsr r4, r4, #8 \n"
1037 " lsr r6, r6, #8 \n"
1038 " bfi r7, r4, #16, #8 \n"
1039 " bfi r12, r6, #16, #8 \n"
1040 " lsr r4, r4, #16 \n"
1041 " lsr r6, r6, #16 \n"
1042 " bfi r7, r4, #24, #8 \n"
1043 " bfi r12, r6, #24, #8 \n"
1044 " stmia r0!, {r7, r12} \n"
1045 " subs r2, #8 \n"
1046 " bne loop1 \n"
1047 " pop {r1-r7, r12, pc} \n");
1048
1049 }
1050 #if defined(__ICCARM__)
1051 #pragma diag_default = Pe940
1052 #endif
1053 #else
1054 #error Toolchain not supported.
1055 #endif
1056
1057 static void CSI_MemCopy(void *pDest, const void *pSrc, size_t cnt)
1058 {
1059 (void)memcpy(pDest, pSrc, cnt);
1060 }
1061
1062
1063
1064
1065
1066
1067
1068
1069 void CSI_FragModeInit(CSI_Type *base)
1070 {
1071 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1072 uint32_t instance = CSI_GetInstance(base);
1073 CLOCK_EnableClock(s_csiClocks[instance]);
1074 #endif
1075
1076 CSI_Reset(base);
1077 }
1078
1079
1080
1081
1082
1083
1084
1085
1086 void CSI_FragModeDeinit(CSI_Type *base)
1087 {
1088 CSI_Deinit(base);
1089 }
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103 status_t CSI_FragModeCreateHandle(CSI_Type *base,
1104 csi_frag_handle_t *handle,
1105 const csi_frag_config_t *config,
1106 csi_frag_transfer_callback_t callback,
1107 void *userData)
1108 {
1109 assert(NULL != config);
1110 uint32_t reg;
1111 uint32_t instance;
1112 uint32_t imgWidth_Bytes;
1113
1114 if (config->dataBus != kCSI_DataBus8Bit)
1115 {
1116 return kStatus_InvalidArgument;
1117 }
1118
1119 imgWidth_Bytes = (uint32_t)config->width * CSI_FRAG_INPUT_BYTES_PER_PIXEL;
1120
1121
1122 if ((imgWidth_Bytes & 0x07U) != 0U)
1123 {
1124 return kStatus_InvalidArgument;
1125 }
1126
1127
1128 if (config->height % config->dmaBufferLine != 0U)
1129 {
1130 return kStatus_InvalidArgument;
1131 }
1132
1133 (void)memset(handle, 0, sizeof(*handle));
1134 handle->callback = callback;
1135 handle->userData = userData;
1136 handle->height = config->height;
1137 handle->width = config->width;
1138 handle->maxLinePerFrag = config->dmaBufferLine;
1139 handle->dmaBytePerLine = config->width * CSI_FRAG_INPUT_BYTES_PER_PIXEL;
1140 handle->isDmaBufferCachable = config->isDmaBufferCachable;
1141
1142
1143 instance = CSI_GetInstance(base);
1144
1145 s_csiHandle[instance] = handle;
1146
1147 s_csiIsr = CSI_FragModeTransferHandleIRQ;
1148
1149 (void)EnableIRQ(s_csiIRQ[instance]);
1150
1151
1152 reg = ((uint32_t)config->workMode) | config->polarityFlags | CSI_CR1_FCC_MASK;
1153
1154 if (config->useExtVsync)
1155 {
1156 reg |= CSI_CR1_EXT_VSYNC_MASK;
1157 }
1158
1159 CSI_REG_CR1(base) = reg;
1160
1161
1162 CSI_REG_FBUF_PARA(base) = 0;
1163
1164
1165 CSI_REG_CR3(base) |= CSI_CR3_ECC_AUTO_EN_MASK;
1166
1167
1168
1169
1170
1171
1172 if (0U == (imgWidth_Bytes % (8U * 16U)))
1173 {
1174 CSI_REG_CR2(base) = CSI_CR2_DMA_BURST_TYPE_RFF(3U);
1175 CSI_REG_CR3(base) = (CSI_REG_CR3(base) & ~CSI_CR3_RxFF_LEVEL_MASK) | ((2U << CSI_CR3_RxFF_LEVEL_SHIFT));
1176 }
1177 else if (0U == (imgWidth_Bytes % (8U * 8U)))
1178 {
1179 CSI_REG_CR2(base) = CSI_CR2_DMA_BURST_TYPE_RFF(2U);
1180 CSI_REG_CR3(base) = (CSI_REG_CR3(base) & ~CSI_CR3_RxFF_LEVEL_MASK) | ((1U << CSI_CR3_RxFF_LEVEL_SHIFT));
1181 }
1182 else
1183 {
1184 CSI_REG_CR2(base) = CSI_CR2_DMA_BURST_TYPE_RFF(1U);
1185 CSI_REG_CR3(base) = (CSI_REG_CR3(base) & ~CSI_CR3_RxFF_LEVEL_MASK) | ((0U << CSI_CR3_RxFF_LEVEL_SHIFT));
1186 }
1187
1188 CSI_REG_DMASA_FB1(base) = CSI_ADDR_CPU_2_IP(config->dmaBufferAddr0);
1189 CSI_REG_DMASA_FB2(base) = CSI_ADDR_CPU_2_IP(config->dmaBufferAddr1);
1190
1191 if (handle->isDmaBufferCachable)
1192 {
1193 DCACHE_CleanInvalidateByRange(
1194 config->dmaBufferAddr0,
1195 (uint32_t)config->dmaBufferLine * (uint32_t)config->width * CSI_FRAG_INPUT_BYTES_PER_PIXEL);
1196 DCACHE_CleanInvalidateByRange(
1197 config->dmaBufferAddr1,
1198 (uint32_t)config->dmaBufferLine * (uint32_t)config->width * CSI_FRAG_INPUT_BYTES_PER_PIXEL);
1199 }
1200
1201 return kStatus_Success;
1202 }
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214 status_t CSI_FragModeTransferCaptureImage(CSI_Type *base,
1215 csi_frag_handle_t *handle,
1216 const csi_frag_capture_config_t *config)
1217 {
1218 assert(NULL != config);
1219
1220 uint16_t windowWidth;
1221
1222
1223
1224
1225
1226 if (config->window != NULL)
1227 {
1228 handle->windowULX = config->window->windowULX;
1229 handle->windowULY = config->window->windowULY;
1230 handle->windowLRX = config->window->windowLRX;
1231 handle->windowLRY = config->window->windowLRY;
1232 handle->linePerFrag = 1;
1233 }
1234 else
1235 {
1236 handle->windowULX = 0;
1237 handle->windowULY = 0;
1238 handle->windowLRX = handle->width - 1U;
1239 handle->windowLRY = handle->height - 1U;
1240 handle->linePerFrag = handle->maxLinePerFrag;
1241 }
1242
1243 windowWidth = handle->windowLRX - handle->windowULX + 1U;
1244
1245 if (config->outputGrayScale)
1246 {
1247
1248 if (windowWidth % 8U != 0U)
1249 {
1250 return kStatus_InvalidArgument;
1251 }
1252
1253 handle->datBytePerLine = windowWidth;
1254 if (handle->inputFormat == kCSI_FragInputYUYV)
1255 {
1256 handle->copyFunc = CSI_ExtractYFromYUYV;
1257 }
1258 else
1259 {
1260 handle->copyFunc = CSI_ExtractYFromUYVY;
1261 }
1262 }
1263 else
1264 {
1265 handle->datBytePerLine = windowWidth * CSI_FRAG_INPUT_BYTES_PER_PIXEL;
1266 handle->copyFunc = CSI_MemCopy;
1267 }
1268
1269 handle->dmaCurLine = 0;
1270 handle->outputBuffer = (uint32_t)config->buffer;
1271 handle->datCurWriteAddr = (uint32_t)config->buffer;
1272
1273
1274 CSI_REG_IMAG_PARA(base) =
1275 (((uint32_t)handle->width * CSI_FRAG_INPUT_BYTES_PER_PIXEL) << CSI_IMAG_PARA_IMAGE_WIDTH_SHIFT) |
1276 ((uint32_t)(handle->linePerFrag) << CSI_IMAG_PARA_IMAGE_HEIGHT_SHIFT);
1277
1278
1279
1280
1281
1282 CSI_REG_CR18(base) = (CSI_REG_CR18(base) & ~CSI_CR18_MASK_OPTION_MASK) | CSI_CR18_MASK_OPTION(0);
1283
1284 CSI_EnableInterrupts(base, (uint32_t)kCSI_StartOfFrameInterruptEnable |
1285 (uint32_t)kCSI_RxBuffer1DmaDoneInterruptEnable |
1286 (uint32_t)kCSI_RxBuffer0DmaDoneInterruptEnable);
1287
1288 return kStatus_Success;
1289 }
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299 void CSI_FragModeTransferAbortCaptureImage(CSI_Type *base, csi_frag_handle_t *handle)
1300 {
1301 CSI_Stop(base);
1302 CSI_DisableInterrupts(base, (uint32_t)kCSI_StartOfFrameInterruptEnable |
1303 (uint32_t)kCSI_RxBuffer1DmaDoneInterruptEnable |
1304 (uint32_t)kCSI_RxBuffer0DmaDoneInterruptEnable);
1305 }
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316 void CSI_FragModeTransferHandleIRQ(CSI_Type *base, csi_frag_handle_t *handle)
1317 {
1318 uint32_t csisr = CSI_REG_SR(base);
1319 uint32_t dmaBufAddr;
1320 uint16_t line;
1321 pvoid_to_u32_t memSrc;
1322 pvoid_to_u32_t memDest;
1323
1324
1325 CSI_REG_SR(base) = csisr;
1326
1327
1328 if (0U != (csisr & (uint32_t)kCSI_StartOfFrameFlag))
1329 {
1330
1331 CSI_REG_CR3(base) |= (CSI_CR3_DMA_REFLASH_RFF_MASK | CSI_CR3_DMA_REQ_EN_RFF_MASK);
1332 CSI_Start(base);
1333 handle->dmaCurLine = 0;
1334 handle->datCurWriteAddr = handle->outputBuffer;
1335 }
1336 else if ((csisr & (CSI_SR_DMA_TSF_DONE_FB2_MASK | CSI_SR_DMA_TSF_DONE_FB1_MASK)) != 0U)
1337 {
1338 if ((csisr & CSI_SR_DMA_TSF_DONE_FB1_MASK) == CSI_SR_DMA_TSF_DONE_FB1_MASK)
1339 {
1340 dmaBufAddr = CSI_REG_DMASA_FB1(base);
1341 }
1342 else
1343 {
1344 dmaBufAddr = CSI_REG_DMASA_FB2(base);
1345 }
1346
1347 dmaBufAddr = CSI_ADDR_IP_2_CPU(dmaBufAddr);
1348
1349 if (handle->isDmaBufferCachable)
1350 {
1351 DCACHE_InvalidateByRange(dmaBufAddr, (uint32_t)handle->dmaBytePerLine * (uint32_t)handle->linePerFrag);
1352 }
1353
1354
1355 dmaBufAddr += ((uint32_t)handle->windowULX * CSI_FRAG_INPUT_BYTES_PER_PIXEL);
1356
1357 for (line = 0; line < handle->linePerFrag; line++)
1358 {
1359 if (handle->dmaCurLine + line > handle->windowLRY)
1360 {
1361
1362 break;
1363 }
1364 else if (handle->dmaCurLine + line >= handle->windowULY)
1365 {
1366 memDest.u32 = handle->datCurWriteAddr;
1367 memSrc.u32 = dmaBufAddr;
1368
1369 handle->copyFunc(memDest.pvoid, memSrc.pvoid, handle->datBytePerLine);
1370 handle->datCurWriteAddr += handle->datBytePerLine;
1371 dmaBufAddr += handle->dmaBytePerLine;
1372 }
1373 else
1374 {
1375 ;
1376 }
1377 }
1378
1379 handle->dmaCurLine += handle->linePerFrag;
1380
1381 if (handle->dmaCurLine >= handle->height)
1382 {
1383 CSI_Stop(base);
1384 CSI_DisableInterrupts(base, (uint32_t)kCSI_StartOfFrameInterruptEnable |
1385 (uint32_t)kCSI_RxBuffer1DmaDoneInterruptEnable |
1386 (uint32_t)kCSI_RxBuffer0DmaDoneInterruptEnable);
1387
1388
1389 if (NULL != handle->callback)
1390 {
1391 handle->callback(base, handle, kStatus_CSI_FrameDone, handle->userData);
1392 }
1393 }
1394 }
1395 else
1396 {
1397 }
1398 }
1399 #endif
1400
1401 #if defined(CSI)
1402 void CSI_DriverIRQHandler(void);
1403 void CSI_DriverIRQHandler(void)
1404 {
1405 s_csiIsr(CSI, s_csiHandle[0]);
1406 SDK_ISR_EXIT_BARRIER;
1407 }
1408 #endif
1409
1410 #if defined(CSI0)
1411 void CSI0_DriverIRQHandler(void);
1412 void CSI0_DriverIRQHandler(void)
1413 {
1414 s_csiIsr(CSI, s_csiHandle[0]);
1415 SDK_ISR_EXIT_BARRIER;
1416 }
1417 #endif