123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296 |
- /**************************************************************************//**
- *
- * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-7-15 Wayne First version
- *
- ******************************************************************************/
- #include <rtconfig.h>
- #if defined(BSP_USING_PDMA)
- #include <rtdevice.h>
- #include <rtthread.h>
- #include <drv_pdma.h>
- #include <nu_bitutil.h>
- #include "drv_sys.h"
- /* Private define ---------------------------------------------------------------*/
- // RT_DEV_NAME_PREFIX pdma
- #ifndef NU_PDMA_MEMFUN_ACTOR_MAX
- #define NU_PDMA_MEMFUN_ACTOR_MAX (4)
- #endif
- /* To select the first PDMA base */
- #if !defined(USE_MA35D1_SUBM)
- #define DEF_PDMA_BASE_START PDMA0_BASE
- #else
- #define DEF_PDMA_BASE_START PDMA2_BASE
- #endif
- enum
- {
- PDMA_START = -1,
- #if defined(BSP_USING_PDMA0)
- PDMA0_IDX,
- #endif
- #if defined(BSP_USING_PDMA1)
- PDMA1_IDX,
- #endif
- #if defined(BSP_USING_PDMA2)
- PDMA2_IDX,
- #endif
- #if defined(BSP_USING_PDMA3)
- PDMA3_IDX,
- #endif
- PDMA_CNT
- };
- #define NU_PDMA_SG_TBL_MAXSIZE (NU_PDMA_SG_LIMITED_DISTANCE/sizeof(DSCT_T))
- #define NU_PDMA_CH_MAX (PDMA_CNT*PDMA_CH_MAX) /* Specify maximum channels of PDMA */
- #define NU_PDMA_CH_Pos (0) /* Specify first channel number of PDMA */
- #define NU_PDMA_CH_Msk (PDMA_CH_Msk << NU_PDMA_CH_Pos)
- #define NU_PDMA_GET_BASE(ch) (PDMA_T *)((((ch)/PDMA_CH_MAX)*0x10000UL) + DEF_PDMA_BASE_START)
- #define NU_PDMA_GET_MOD_IDX(ch) ((ch)/PDMA_CH_MAX)
- #define NU_PDMA_GET_MOD_CHIDX(ch) ((ch)%PDMA_CH_MAX)
- /* Private typedef --------------------------------------------------------------*/
- struct nu_pdma_periph_ctl
- {
- uint32_t m_u32Peripheral;
- nu_pdma_memctrl_t m_eMemCtl;
- };
- typedef struct nu_pdma_periph_ctl nu_pdma_periph_ctl_t;
- struct nu_pdma_chn
- {
- struct nu_pdma_chn_cb m_sCB_Event;
- struct nu_pdma_chn_cb m_sCB_Trigger;
- struct nu_pdma_chn_cb m_sCB_Disable;
- nu_pdma_desc_t *m_ppsSgtbl;
- uint32_t m_u32WantedSGTblNum;
- uint32_t m_u32EventFilter;
- uint32_t m_u32IdleTimeout_us;
- nu_pdma_periph_ctl_t m_spPeripCtl;
- };
- typedef struct nu_pdma_chn nu_pdma_chn_t;
- struct nu_pdma_memfun_actor
- {
- int m_i32ChannID;
- uint32_t m_u32Result;
- rt_sem_t m_psSemMemFun;
- } ;
- typedef struct nu_pdma_memfun_actor *nu_pdma_memfun_actor_t;
- /* Private functions ------------------------------------------------------------*/
- static int nu_pdma_peripheral_set(uint32_t u32PeriphType);
- static void nu_pdma_init(void);
- static void nu_pdma_channel_enable(int i32ChannID);
- static void nu_pdma_channel_disable(int i32ChannID);
- static void nu_pdma_channel_reset(int i32ChannID);
- static rt_err_t nu_pdma_timeout_set(int i32ChannID, int i32Timeout_us);
- static void nu_pdma_periph_ctrl_fill(int i32ChannID, int i32CtlPoolIdx);
- static rt_size_t nu_pdma_memfun(void *dest, void *src, uint32_t u32DataWidth, unsigned int u32TransferCnt, nu_pdma_memctrl_t eMemCtl);
- static void nu_pdma_memfun_cb(void *pvUserData, uint32_t u32Events);
- static void nu_pdma_memfun_actor_init(void);
- static int nu_pdma_memfun_employ(void);
- static int nu_pdma_non_transfer_count_get(int32_t i32ChannID);
- /* Public functions -------------------------------------------------------------*/
- /* Private variables ------------------------------------------------------------*/
- static volatile int nu_pdma_inited = 0;
- static volatile uint32_t nu_pdma_chn_mask_arr[PDMA_CNT] = {0};
- static nu_pdma_chn_t nu_pdma_chn_arr[NU_PDMA_CH_MAX];
- static volatile uint32_t nu_pdma_memfun_actor_mask = 0;
- static volatile uint32_t nu_pdma_memfun_actor_maxnum = 0;
- static rt_sem_t nu_pdma_memfun_actor_pool_sem = RT_NULL;
- static rt_mutex_t nu_pdma_memfun_actor_pool_lock = RT_NULL;
- static void nu_pdma_isr(int vector, void *pvdata);
- const static struct nu_module nu_pdma_arr[] =
- {
- #if defined(BSP_USING_PDMA0)
- {
- .name = "pdma0",
- .m_pvBase = (void *)PDMA0,
- .u32RstId = PDMA0_RST,
- .eIRQn = PDMA0_IRQn
- },
- #endif
- #if defined(BSP_USING_PDMA1)
- {
- .name = "pdma1",
- .m_pvBase = (void *)PDMA1,
- .u32RstId = PDMA1_RST,
- .eIRQn = PDMA1_IRQn
- },
- #endif
- #if defined(BSP_USING_PDMA2)
- {
- .name = "pdma2",
- .m_pvBase = (void *)PDMA2,
- .u32RstId = PDMA2_RST,
- .eIRQn = PDMA2_IRQn
- },
- #endif
- #if defined(BSP_USING_PDMA3)
- {
- .name = "pdma3",
- .m_pvBase = (void *)PDMA3,
- .u32RstId = PDMA3_RST,
- .eIRQn = PDMA3_IRQn
- }
- #endif
- };
- static const nu_pdma_periph_ctl_t g_nu_pdma_peripheral_ctl_pool[ ] =
- {
- // M2M
- { PDMA_MEM, eMemCtl_SrcInc_DstInc },
- // M2P
- { PDMA_UART0_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART1_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART2_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART3_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART4_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART5_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART6_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART7_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART8_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART9_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART10_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART11_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART12_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART13_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART14_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART15_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_UART16_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_QSPI0_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_QSPI1_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_SPI0_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_SPI1_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_SPI2_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_SPI3_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_I2C0_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_I2C1_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_I2C2_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_I2C3_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_I2C4_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_I2C5_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_I2S0_TX, eMemCtl_SrcInc_DstFix },
- { PDMA_I2S1_TX, eMemCtl_SrcInc_DstFix },
- // P2M
- { PDMA_UART0_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART1_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART2_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART3_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART4_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART5_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART6_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART7_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART8_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART9_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART10_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART11_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART12_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART13_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART14_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART15_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_UART16_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_QSPI0_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_QSPI1_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_SPI0_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_SPI1_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_SPI2_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_SPI3_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_I2C0_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_I2C1_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_I2C2_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_I2C3_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_I2C4_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_I2C5_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_I2S0_RX, eMemCtl_SrcFix_DstInc },
- { PDMA_I2S1_RX, eMemCtl_SrcFix_DstInc },
- };
- #define NU_PERIPHERAL_SIZE ( sizeof(g_nu_pdma_peripheral_ctl_pool) / sizeof(g_nu_pdma_peripheral_ctl_pool[0]) )
- static struct nu_pdma_memfun_actor nu_pdma_memfun_actor_arr[NU_PDMA_MEMFUN_ACTOR_MAX];
- static int nu_pdma_check_is_nonallocated(uint32_t u32ChnId)
- {
- uint32_t mod_idx = NU_PDMA_GET_MOD_IDX(u32ChnId);
- RT_ASSERT(mod_idx < PDMA_CNT);
- return !(nu_pdma_chn_mask_arr[mod_idx] & (1 << NU_PDMA_GET_MOD_CHIDX(u32ChnId)));
- }
- static int nu_pdma_peripheral_set(uint32_t u32PeriphType)
- {
- int idx = 0;
- while (idx < NU_PERIPHERAL_SIZE)
- {
- if (g_nu_pdma_peripheral_ctl_pool[idx].m_u32Peripheral == u32PeriphType)
- return idx;
- idx++;
- }
- // Not such peripheral
- return -1;
- }
- static void nu_pdma_periph_ctrl_fill(int i32ChannID, int i32CtlPoolIdx)
- {
- nu_pdma_chn_t *psPdmaChann = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos];
- psPdmaChann->m_spPeripCtl.m_u32Peripheral = g_nu_pdma_peripheral_ctl_pool[i32CtlPoolIdx].m_u32Peripheral;
- psPdmaChann->m_spPeripCtl.m_eMemCtl = g_nu_pdma_peripheral_ctl_pool[i32CtlPoolIdx].m_eMemCtl;
- }
- /**
- * Hardware PDMA Initialization
- */
- static void nu_pdma_init(void)
- {
- int i;
- if (nu_pdma_inited)
- return;
- rt_memset(nu_pdma_chn_arr, 0x00, NU_PDMA_CH_MAX * sizeof(nu_pdma_chn_t));
- for (i = (PDMA_START + 1); i < PDMA_CNT; i++)
- {
- nu_pdma_chn_mask_arr[i] = ~(NU_PDMA_CH_Msk);
- nu_sys_ip_reset(nu_pdma_arr[i].u32RstId);
- /* Initialize PDMA setting */
- PDMA_Open((PDMA_T *)nu_pdma_arr[i].m_pvBase, PDMA_CH_Msk);
- PDMA_Close((PDMA_T *)nu_pdma_arr[i].m_pvBase);
- /* Register PDMA ISR */
- rt_hw_interrupt_install(nu_pdma_arr[i].eIRQn, nu_pdma_isr, nu_pdma_arr[i].m_pvBase, nu_pdma_arr[i].name);
- rt_hw_interrupt_umask(nu_pdma_arr[i].eIRQn);
- }
- nu_pdma_inited = 1;
- }
- static inline void nu_pdma_channel_enable(int i32ChannID)
- {
- PDMA_T *PDMA = NU_PDMA_GET_BASE(i32ChannID);
- int u32ModChannId = NU_PDMA_GET_MOD_CHIDX(i32ChannID);
- /* Clean descriptor table control register. */
- PDMA->DSCT[u32ModChannId].CTL = 0UL;
- /* Enable the channel */
- PDMA->CHCTL |= (1 << u32ModChannId);
- }
- static inline void nu_pdma_channel_disable(int i32ChannID)
- {
- PDMA_T *PDMA = NU_PDMA_GET_BASE(i32ChannID);
- PDMA->CHCTL &= ~(1 << NU_PDMA_GET_MOD_CHIDX(i32ChannID));
- }
- static inline void nu_pdma_channel_reset(int i32ChannID)
- {
- PDMA_T *PDMA = NU_PDMA_GET_BASE(i32ChannID);
- int u32ModChannId = NU_PDMA_GET_MOD_CHIDX(i32ChannID);
- PDMA->CHRST = (1 << u32ModChannId);
- /* Wait for cleared channel CHCTL. */
- while ((PDMA->CHCTL & (1 << u32ModChannId)));
- }
- static rt_err_t nu_pdma_timeout_set(int i32ChannID, int i32Timeout_us)
- {
- rt_err_t ret = RT_EINVAL;
- PDMA_T *PDMA = NULL;
- uint32_t u32ModChannId;
- if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_nu_pdma_timeout_set;
- PDMA = NU_PDMA_GET_BASE(i32ChannID);
- u32ModChannId = NU_PDMA_GET_MOD_CHIDX(i32ChannID);
- nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_u32IdleTimeout_us = i32Timeout_us;
- if (i32Timeout_us)
- {
- uint32_t u32ToClk_Max = 1000000ul / (CLK_GetSYSCLK1Freq() / (1 << 8));
- uint32_t u32Divider = (i32Timeout_us / u32ToClk_Max) / (1 << 16);
- uint32_t u32TOutCnt = (i32Timeout_us / u32ToClk_Max) % (1 << 16);
- PDMA_DisableTimeout(PDMA, 1 << u32ModChannId);
- PDMA_EnableInt(PDMA, u32ModChannId, PDMA_INT_TIMEOUT); // Interrupt type
- if (u32Divider > 7)
- {
- u32Divider = 7;
- u32TOutCnt = (1 << 16) - 1;
- }
- if (u32ModChannId < 8)
- PDMA->TOUTPSC = (PDMA->TOUTPSC & ~(0x7ul << (PDMA_TOUTPSC_TOUTPSC1_Pos * u32ModChannId))) | (u32Divider << (PDMA_TOUTPSC_TOUTPSC1_Pos * u32ModChannId));
- else
- PDMA->TOUTPSC1 = (PDMA->TOUTPSC1 & ~(0x7ul << (PDMA_TOUTPSC_TOUTPSC1_Pos * u32ModChannId))) | (u32Divider << (PDMA_TOUTPSC_TOUTPSC1_Pos * u32ModChannId));
- //rt_kprintf("[%d]HCLK=%d, u32Divider=%d, u32TOutCnt=%d\n", i32Timeout_us, CLK_GetSYSCLK1Freq(), u32Divider, u32TOutCnt );
- PDMA_SetTimeOut(PDMA, u32ModChannId, 1, u32TOutCnt);
- ret = RT_EOK;
- }
- else
- {
- PDMA_DisableInt(PDMA, u32ModChannId, PDMA_INT_TIMEOUT); // Interrupt type
- PDMA_DisableTimeout(PDMA, 1 << u32ModChannId);
- }
- exit_nu_pdma_timeout_set:
- return -(ret);
- }
- void nu_pdma_channel_terminate(int i32ChannID)
- {
- if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_pdma_channel_terminate;
- /* Disable timeout function of specified channel. */
- nu_pdma_timeout_set(i32ChannID, 0);
- /* Reset specified channel. */
- nu_pdma_channel_reset(i32ChannID);
- /* Enable specified channel after reset. */
- nu_pdma_channel_enable(i32ChannID);
- exit_pdma_channel_terminate:
- return;
- }
- int nu_pdma_channel_allocate(int32_t i32PeripType)
- {
- int ChnId, i32PeripCtlIdx, j;
- nu_pdma_init();
- if ((i32PeripCtlIdx = nu_pdma_peripheral_set(i32PeripType)) < 0)
- goto exit_nu_pdma_channel_allocate;
- for (j = (PDMA_START + 1); j < PDMA_CNT; j++)
- {
- /* Find the position of first '0' in nu_pdma_chn_mask_arr[j]. */
- ChnId = nu_cto(nu_pdma_chn_mask_arr[j]);
- if (ChnId < PDMA_CH_MAX)
- {
- nu_pdma_chn_mask_arr[j] |= (1 << ChnId);
- ChnId += (j * PDMA_CH_MAX);
- rt_memset(nu_pdma_chn_arr + ChnId - NU_PDMA_CH_Pos, 0x00, sizeof(nu_pdma_chn_t));
- /* Set idx number of g_nu_pdma_peripheral_ctl_pool */
- nu_pdma_periph_ctrl_fill(ChnId, i32PeripCtlIdx);
- /* Reset channel */
- nu_pdma_channel_terminate(ChnId);
- return ChnId;
- }
- }
- exit_nu_pdma_channel_allocate:
- // No channel available
- return -(RT_ERROR);
- }
- rt_err_t nu_pdma_channel_free(int i32ChannID)
- {
- rt_err_t ret = RT_EINVAL;
- if (! nu_pdma_inited)
- goto exit_nu_pdma_channel_free;
- if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_nu_pdma_channel_free;
- if ((i32ChannID < NU_PDMA_CH_MAX) && (i32ChannID >= NU_PDMA_CH_Pos))
- {
- nu_pdma_chn_mask_arr[NU_PDMA_GET_MOD_IDX(i32ChannID)] &= ~(1 << NU_PDMA_GET_MOD_CHIDX(i32ChannID));
- nu_pdma_channel_disable(i32ChannID);
- ret = RT_EOK;
- }
- exit_nu_pdma_channel_free:
- return -(ret);
- }
- rt_err_t nu_pdma_filtering_set(int i32ChannID, uint32_t u32EventFilter)
- {
- rt_err_t ret = RT_EINVAL;
- if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_nu_pdma_filtering_set;
- nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_u32EventFilter = u32EventFilter;
- ret = RT_EOK;
- exit_nu_pdma_filtering_set:
- return -(ret) ;
- }
- uint32_t nu_pdma_filtering_get(int i32ChannID)
- {
- if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_nu_pdma_filtering_get;
- return nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_u32EventFilter;
- exit_nu_pdma_filtering_get:
- return 0;
- }
- rt_err_t nu_pdma_callback_register(int i32ChannID, nu_pdma_chn_cb_t psChnCb)
- {
- rt_err_t ret = RT_EINVAL;
- nu_pdma_chn_cb_t psChnCb_Current = RT_NULL;
- RT_ASSERT(psChnCb != RT_NULL);
- if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_nu_pdma_callback_register;
- switch (psChnCb->m_eCBType)
- {
- case eCBType_Event:
- psChnCb_Current = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_sCB_Event;
- break;
- case eCBType_Trigger:
- psChnCb_Current = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_sCB_Trigger;
- break;
- case eCBType_Disable:
- psChnCb_Current = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_sCB_Disable;
- break;
- default:
- goto exit_nu_pdma_callback_register;
- }
- psChnCb_Current->m_pfnCBHandler = psChnCb->m_pfnCBHandler;
- psChnCb_Current->m_pvUserData = psChnCb->m_pvUserData;
- ret = RT_EOK;
- exit_nu_pdma_callback_register:
- return -(ret) ;
- }
- nu_pdma_cb_handler_t nu_pdma_callback_hijack(int i32ChannID, nu_pdma_cbtype_t eCBType, nu_pdma_chn_cb_t psChnCb_Hijack)
- {
- nu_pdma_chn_cb_t psChnCb_Current = RT_NULL;
- struct nu_pdma_chn_cb sChnCB_Tmp;
- RT_ASSERT(psChnCb_Hijack != NULL);
- sChnCB_Tmp.m_pfnCBHandler = RT_NULL;
- if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_nu_pdma_callback_hijack;
- switch (eCBType)
- {
- case eCBType_Event:
- psChnCb_Current = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_sCB_Event;
- break;
- case eCBType_Trigger:
- psChnCb_Current = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_sCB_Trigger;
- break;
- case eCBType_Disable:
- psChnCb_Current = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_sCB_Disable;
- break;
- default:
- goto exit_nu_pdma_callback_hijack;
- }
- /* Backup */
- sChnCB_Tmp.m_pfnCBHandler = psChnCb_Current->m_pfnCBHandler;
- sChnCB_Tmp.m_pvUserData = psChnCb_Current->m_pvUserData;
- /* Update */
- psChnCb_Current->m_pfnCBHandler = psChnCb_Hijack->m_pfnCBHandler;
- psChnCb_Current->m_pvUserData = psChnCb_Hijack->m_pvUserData;
- /* Restore */
- psChnCb_Hijack->m_pfnCBHandler = sChnCB_Tmp.m_pfnCBHandler;
- psChnCb_Hijack->m_pvUserData = sChnCB_Tmp.m_pvUserData;
- exit_nu_pdma_callback_hijack:
- return sChnCB_Tmp.m_pfnCBHandler;
- }
- static int nu_pdma_non_transfer_count_get(int32_t i32ChannID)
- {
- PDMA_T *PDMA = NU_PDMA_GET_BASE(i32ChannID);
- return ((PDMA->DSCT[NU_PDMA_GET_MOD_CHIDX(i32ChannID)].CTL & PDMA_DSCT_CTL_TXCNT_Msk) >> PDMA_DSCT_CTL_TXCNT_Pos) + 1;
- }
- int nu_pdma_transferred_byte_get(int32_t i32ChannID, int32_t i32TriggerByteLen)
- {
- int i32BitWidth = 0;
- int cur_txcnt = 0;
- PDMA_T *PDMA;
- if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_nu_pdma_transferred_byte_get;
- PDMA = NU_PDMA_GET_BASE(i32ChannID);
- if ((PDMA->DSCT[NU_PDMA_GET_MOD_CHIDX(i32ChannID)].CTL & PDMA_DSCT_CTL_OPMODE_Msk) != PDMA_OP_SCATTER)
- {
- i32BitWidth = PDMA->DSCT[NU_PDMA_GET_MOD_CHIDX(i32ChannID)].CTL & PDMA_DSCT_CTL_TXWIDTH_Msk;
- i32BitWidth = (i32BitWidth == PDMA_WIDTH_8) ? 1 : (i32BitWidth == PDMA_WIDTH_16) ? 2 : (i32BitWidth == PDMA_WIDTH_32) ? 4 : 0;
- cur_txcnt = nu_pdma_non_transfer_count_get(i32ChannID);
- // rt_kprintf("\n[%s] %d %d %02x\n", __func__, i32ChannID, cur_txcnt, (PDMA->DSCT[NU_PDMA_GET_MOD_CHIDX(i32ChannID)].CTL & PDMA_DSCT_CTL_OPMODE_Msk) );
- return (i32TriggerByteLen - (cur_txcnt) * i32BitWidth);
- }
- // rt_kprintf("\n@@@@ %d %02x @@@@\n", i32ChannID, PDMA->DSCT[NU_PDMA_GET_MOD_CHIDX(i32ChannID)].CTL & PDMA_DSCT_CTL_OPMODE_Msk);
- return 0;
- exit_nu_pdma_transferred_byte_get:
- return -1;
- }
- nu_pdma_desc_t nu_pdma_get_channel_desc(int32_t i32ChannID)
- {
- PDMA_T *PDMA;
- if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_nu_pdma_get_srcaddr;
- PDMA = NU_PDMA_GET_BASE(i32ChannID);
- return &PDMA->DSCT[NU_PDMA_GET_MOD_CHIDX(i32ChannID)];
- exit_nu_pdma_get_srcaddr:
- return RT_NULL;
- }
- nu_pdma_memctrl_t nu_pdma_channel_memctrl_get(int i32ChannID)
- {
- nu_pdma_memctrl_t eMemCtrl = eMemCtl_Undefined;
- if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_nu_pdma_channel_memctrl_get;
- eMemCtrl = nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_spPeripCtl.m_eMemCtl;
- exit_nu_pdma_channel_memctrl_get:
- return eMemCtrl;
- }
- rt_err_t nu_pdma_channel_memctrl_set(int i32ChannID, nu_pdma_memctrl_t eMemCtrl)
- {
- rt_err_t ret = RT_EINVAL;
- nu_pdma_chn_t *psPdmaChann = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos];
- if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_nu_pdma_channel_memctrl_set;
- else if ((eMemCtrl < eMemCtl_SrcFix_DstFix) || (eMemCtrl > eMemCtl_SrcInc_DstInc))
- goto exit_nu_pdma_channel_memctrl_set;
- /* PDMA_MEM/SAR_FIX/BURST mode is not supported. */
- if ((psPdmaChann->m_spPeripCtl.m_u32Peripheral == PDMA_MEM) &&
- ((eMemCtrl == eMemCtl_SrcFix_DstInc) || (eMemCtrl == eMemCtl_SrcFix_DstFix)))
- goto exit_nu_pdma_channel_memctrl_set;
- nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_spPeripCtl.m_eMemCtl = eMemCtrl;
- ret = RT_EOK;
- exit_nu_pdma_channel_memctrl_set:
- return -(ret);
- }
- static void nu_pdma_channel_memctrl_fill(nu_pdma_memctrl_t eMemCtl, uint32_t *pu32SrcCtl, uint32_t *pu32DstCtl)
- {
- switch ((int)eMemCtl)
- {
- case eMemCtl_SrcFix_DstFix:
- *pu32SrcCtl = PDMA_SAR_FIX;
- *pu32DstCtl = PDMA_DAR_FIX;
- break;
- case eMemCtl_SrcFix_DstInc:
- *pu32SrcCtl = PDMA_SAR_FIX;
- *pu32DstCtl = PDMA_DAR_INC;
- break;
- case eMemCtl_SrcInc_DstFix:
- *pu32SrcCtl = PDMA_SAR_INC;
- *pu32DstCtl = PDMA_DAR_FIX;
- break;
- case eMemCtl_SrcInc_DstInc:
- *pu32SrcCtl = PDMA_SAR_INC;
- *pu32DstCtl = PDMA_DAR_INC;
- break;
- default:
- break;
- }
- }
- /* This is for Scatter-gather DMA. */
- rt_err_t nu_pdma_desc_setup(int i32ChannID, nu_pdma_desc_t dma_desc, uint32_t u32DataWidth, uint32_t u32AddrSrc,
- uint32_t u32AddrDst, int32_t i32TransferCnt, nu_pdma_desc_t next, uint32_t u32BeSilent)
- {
- nu_pdma_periph_ctl_t *psPeriphCtl = NULL;
- uint32_t u32SrcCtl = 0;
- uint32_t u32DstCtl = 0;
- rt_err_t ret = RT_EINVAL;
- if (!dma_desc)
- goto exit_nu_pdma_desc_setup;
- else if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_nu_pdma_desc_setup;
- else if (!(u32DataWidth == 8 || u32DataWidth == 16 || u32DataWidth == 32))
- goto exit_nu_pdma_desc_setup;
- else if ((u32AddrSrc % (u32DataWidth / 8)) || (u32AddrDst % (u32DataWidth / 8)))
- goto exit_nu_pdma_desc_setup;
- else if (i32TransferCnt > NU_PDMA_MAX_TXCNT)
- goto exit_nu_pdma_desc_setup;
- psPeriphCtl = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_spPeripCtl;
- nu_pdma_channel_memctrl_fill(psPeriphCtl->m_eMemCtl, &u32SrcCtl, &u32DstCtl);
- dma_desc->CTL = ((i32TransferCnt - 1) << PDMA_DSCT_CTL_TXCNT_Pos) |
- ((u32DataWidth == 8) ? PDMA_WIDTH_8 : (u32DataWidth == 16) ? PDMA_WIDTH_16 : PDMA_WIDTH_32) |
- u32SrcCtl |
- u32DstCtl |
- PDMA_OP_BASIC;
- dma_desc->SA = u32AddrSrc;
- dma_desc->DA = u32AddrDst;
- dma_desc->NEXT = 0; /* Terminating node by default. */
- if (psPeriphCtl->m_u32Peripheral == PDMA_MEM)
- {
- /* For M2M transfer */
- dma_desc->CTL |= (PDMA_REQ_BURST | PDMA_BURST_32);
- }
- else
- {
- /* For P2M and M2P transfer */
- dma_desc->CTL |= (PDMA_REQ_SINGLE);
- }
- if (next)
- {
- /* Link to Next and modify to scatter-gather DMA mode. */
- dma_desc->CTL = (dma_desc->CTL & ~PDMA_DSCT_CTL_OPMODE_Msk) | PDMA_OP_SCATTER;
- dma_desc->NEXT = (uint32_t)next;
- }
- /* Be silent */
- if (u32BeSilent)
- dma_desc->CTL |= PDMA_DSCT_CTL_TBINTDIS_Msk;
- ret = RT_EOK;
- exit_nu_pdma_desc_setup:
- return -(ret);
- }
- rt_err_t nu_pdma_sgtbls_allocate(nu_pdma_desc_t *ppsSgtbls, int num)
- {
- int i;
- RT_ASSERT(ppsSgtbls != NULL);
- RT_ASSERT(num > 0);
- for (i = 0; i < num; i++)
- {
- ppsSgtbls[i] = (nu_pdma_desc_t) rt_malloc_align(RT_ALIGN(sizeof(DSCT_T), 64), 64);
- RT_ASSERT(ppsSgtbls[i] != RT_NULL);
- rt_memset((void *)ppsSgtbls[i], 0, RT_ALIGN(sizeof(DSCT_T), 64));
- }
- return RT_EOK;
- }
- void nu_pdma_sgtbls_free(nu_pdma_desc_t *ppsSgtbls, int num)
- {
- int i;
- RT_ASSERT(ppsSgtbls != NULL);
- RT_ASSERT(num > 0);
- for (i = 0; i < num; i++)
- {
- rt_free_align(ppsSgtbls[i]);
- }
- }
- static void _nu_pdma_transfer(int i32ChannID, uint32_t u32Peripheral, nu_pdma_desc_t head, uint32_t u32IdleTimeout_us)
- {
- PDMA_T *PDMA = NU_PDMA_GET_BASE(i32ChannID);
- nu_pdma_chn_t *psPdmaChann = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos];
- #if !defined(USE_MA35D1_SUBM)
- /* Writeback data in dcache to memory before transferring. */
- {
- static uint32_t bNonCacheAlignedWarning = 1;
- nu_pdma_desc_t next = head;
- int CACHE_LINE_SIZE = nu_cpu_dcache_line_size();
- while (next != RT_NULL)
- {
- uint32_t u32TxCnt = ((next->CTL & PDMA_DSCT_CTL_TXCNT_Msk) >> PDMA_DSCT_CTL_TXCNT_Pos) + 1;
- uint32_t u32DataWidth = (1 << ((next->CTL & PDMA_DSCT_CTL_TXWIDTH_Msk) >> PDMA_DSCT_CTL_TXWIDTH_Pos));
- uint32_t u32SrcCtl = (next->CTL & PDMA_DSCT_CTL_SAINC_Msk);
- uint32_t u32DstCtl = (next->CTL & PDMA_DSCT_CTL_DAINC_Msk);
- uint32_t u32FlushLen = u32TxCnt * u32DataWidth;
- #if 0
- rt_kprintf("[%s] i32ChannID=%d\n", __func__, i32ChannID);
- rt_kprintf("[%s] PDMA=0x%08x\n", __func__, (uint32_t)PDMA);
- rt_kprintf("[%s] u32TxCnt=%d\n", __func__, u32TxCnt);
- rt_kprintf("[%s] u32DataWidth=%d\n", __func__, u32DataWidth);
- rt_kprintf("[%s] u32SrcCtl=0x%08x\n", __func__, u32SrcCtl);
- rt_kprintf("[%s] u32DstCtl=0x%08x\n", __func__, u32DstCtl);
- rt_kprintf("[%s] u32FlushLen=%d\n", __func__, u32FlushLen);
- rt_kprintf("[%s] DA=%08x\n", __func__, next->DA);
- rt_kprintf("[%s] SA=%08x\n", __func__, next->SA);
- #endif
- /* Flush Src buffer into memory. */
- if ((u32SrcCtl == PDMA_SAR_INC)) // for M2P, M2M
- rt_hw_cpu_dcache_clean_and_invalidate((void *)next->SA, u32FlushLen);
- /* Flush Dst buffer into memory. */
- if ((u32DstCtl == PDMA_DAR_INC)) // for P2M, M2M
- rt_hw_cpu_dcache_clean_and_invalidate((void *)next->DA, u32FlushLen);
- /* Flush descriptor into memory */
- rt_hw_cpu_dcache_clean_and_invalidate((void *)next, sizeof(DSCT_T));
- if (bNonCacheAlignedWarning)
- {
- if ((u32FlushLen & (CACHE_LINE_SIZE - 1)) ||
- (next->SA & (CACHE_LINE_SIZE - 1)) ||
- (next->DA & (CACHE_LINE_SIZE - 1)) ||
- ((rt_uint32_t)next & (CACHE_LINE_SIZE - 1)))
- {
- /*
- Race-condition avoidance between DMA-transferring and DCache write-back:
- Source, destination, DMA descriptor address and length should be aligned at len(CACHE_LINE_SIZE)
- */
- bNonCacheAlignedWarning = 0;
- //rt_kprintf("[PDMA-W]\n");
- }
- }
- next = (nu_pdma_desc_t)next->NEXT;
- if (next == head) break;
- }
- }
- #endif
- nu_pdma_desc_t psDesc = nu_pdma_get_channel_desc(i32ChannID);
- PDMA_DisableTimeout(PDMA, 1 << NU_PDMA_GET_MOD_CHIDX(i32ChannID));
- /* Set scatter-gather mode and head */
- /* Take care the head structure, you should make sure cache-coherence. */
- PDMA_SetTransferMode(PDMA,
- NU_PDMA_GET_MOD_CHIDX(i32ChannID),
- u32Peripheral,
- (head->NEXT != 0) ? 1 : 0,
- (uint32_t)head);
- /* PDMA fetchs description on-demand if SG enabled. We check it valid in here. */
- if ( (u32Peripheral != PDMA_MEM) &&
- (head->NEXT != 0) &&
- (head->DA != psDesc->DA) )
- {
- RT_ASSERT(0);
- }
- PDMA_EnableInt(PDMA, NU_PDMA_GET_MOD_CHIDX(i32ChannID), PDMA_INT_TRANS_DONE);
- nu_pdma_timeout_set(i32ChannID, u32IdleTimeout_us);
- /* If peripheral is M2M, trigger it. */
- if (u32Peripheral == PDMA_MEM)
- {
- PDMA_Trigger(PDMA, NU_PDMA_GET_MOD_CHIDX(i32ChannID));
- }
- else if (psPdmaChann->m_sCB_Trigger.m_pfnCBHandler)
- {
- psPdmaChann->m_sCB_Trigger.m_pfnCBHandler(psPdmaChann->m_sCB_Trigger.m_pvUserData, psPdmaChann->m_sCB_Trigger.m_u32Reserved);
- }
- }
- static void _nu_pdma_free_sgtbls(nu_pdma_chn_t *psPdmaChann)
- {
- if (psPdmaChann->m_ppsSgtbl)
- {
- nu_pdma_sgtbls_free(psPdmaChann->m_ppsSgtbl, psPdmaChann->m_u32WantedSGTblNum);
- rt_free_align((void *)psPdmaChann->m_ppsSgtbl);
- psPdmaChann->m_ppsSgtbl = RT_NULL;
- psPdmaChann->m_u32WantedSGTblNum = 0;
- }
- }
- static rt_err_t _nu_pdma_transfer_chain(int i32ChannID, uint32_t u32DataWidth, uint32_t u32AddrSrc, uint32_t u32AddrDst, uint32_t u32TransferCnt, uint32_t u32IdleTimeout_us)
- {
- int i = 0;
- rt_err_t ret = RT_ERROR;
- nu_pdma_periph_ctl_t *psPeriphCtl = NULL;
- nu_pdma_chn_t *psPdmaChann = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos];
- nu_pdma_memctrl_t eMemCtl = nu_pdma_channel_memctrl_get(i32ChannID);
- rt_uint32_t u32Offset = 0;
- rt_uint32_t u32TxCnt = 0;
- psPeriphCtl = &psPdmaChann->m_spPeripCtl;
- if (psPdmaChann->m_u32WantedSGTblNum != (u32TransferCnt / NU_PDMA_MAX_TXCNT + 1))
- {
- if (psPdmaChann->m_u32WantedSGTblNum > 0)
- _nu_pdma_free_sgtbls(psPdmaChann);
- psPdmaChann->m_u32WantedSGTblNum = u32TransferCnt / NU_PDMA_MAX_TXCNT + 1;
- psPdmaChann->m_ppsSgtbl = (nu_pdma_desc_t *)rt_malloc_align(sizeof(nu_pdma_desc_t) * psPdmaChann->m_u32WantedSGTblNum, 4);
- if (!psPdmaChann->m_ppsSgtbl)
- goto exit__nu_pdma_transfer_chain;
- ret = nu_pdma_sgtbls_allocate(psPdmaChann->m_ppsSgtbl, psPdmaChann->m_u32WantedSGTblNum);
- if (ret != RT_EOK)
- goto exit__nu_pdma_transfer_chain;
- }
- for (i = 0; i < psPdmaChann->m_u32WantedSGTblNum; i++)
- {
- u32TxCnt = (u32TransferCnt > NU_PDMA_MAX_TXCNT) ? NU_PDMA_MAX_TXCNT : u32TransferCnt;
- ret = nu_pdma_desc_setup(i32ChannID,
- psPdmaChann->m_ppsSgtbl[i],
- u32DataWidth,
- (eMemCtl & 0x2ul) ? u32AddrSrc + u32Offset : u32AddrSrc, /* Src address is Inc or not. */
- (eMemCtl & 0x1ul) ? u32AddrDst + u32Offset : u32AddrDst, /* Dst address is Inc or not. */
- u32TxCnt,
- ((i + 1) == psPdmaChann->m_u32WantedSGTblNum) ? RT_NULL : psPdmaChann->m_ppsSgtbl[i + 1],
- ((i + 1) == psPdmaChann->m_u32WantedSGTblNum) ? 0 : 1); // Silent, w/o TD interrupt
- if (ret != RT_EOK)
- goto exit__nu_pdma_transfer_chain;
- u32TransferCnt -= u32TxCnt;
- u32Offset += (u32TxCnt * u32DataWidth / 8);
- }
- _nu_pdma_transfer(i32ChannID, psPeriphCtl->m_u32Peripheral, psPdmaChann->m_ppsSgtbl[0], u32IdleTimeout_us);
- ret = RT_EOK;
- return ret;
- exit__nu_pdma_transfer_chain:
- _nu_pdma_free_sgtbls(psPdmaChann);
- return -(ret);
- }
- rt_err_t nu_pdma_transfer(int i32ChannID, uint32_t u32DataWidth, uint32_t u32AddrSrc, uint32_t u32AddrDst, uint32_t u32TransferCnt, uint32_t u32IdleTimeout_us)
- {
- rt_err_t ret = RT_EINVAL;
- PDMA_T *PDMA = NU_PDMA_GET_BASE(i32ChannID);
- nu_pdma_desc_t head;
- nu_pdma_chn_t *psPdmaChann;
- nu_pdma_periph_ctl_t *psPeriphCtl = NULL;
- if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_nu_pdma_transfer;
- else if (!u32TransferCnt)
- goto exit_nu_pdma_transfer;
- else if (u32TransferCnt > NU_PDMA_MAX_TXCNT)
- return _nu_pdma_transfer_chain(i32ChannID, u32DataWidth, u32AddrSrc, u32AddrDst, u32TransferCnt, u32IdleTimeout_us);
- psPdmaChann = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos];
- psPeriphCtl = &psPdmaChann->m_spPeripCtl;
- head = &PDMA->DSCT[NU_PDMA_GET_MOD_CHIDX(i32ChannID)];
- ret = nu_pdma_desc_setup(i32ChannID,
- head,
- u32DataWidth,
- u32AddrSrc,
- u32AddrDst,
- u32TransferCnt,
- RT_NULL,
- 0);
- if (ret != RT_EOK)
- goto exit_nu_pdma_transfer;
- _nu_pdma_transfer(i32ChannID, psPeriphCtl->m_u32Peripheral, head, u32IdleTimeout_us);
- ret = RT_EOK;
- exit_nu_pdma_transfer:
- return -(ret);
- }
- rt_err_t nu_pdma_sg_transfer(int i32ChannID, nu_pdma_desc_t head, uint32_t u32IdleTimeout_us)
- {
- rt_err_t ret = RT_EINVAL;
- nu_pdma_periph_ctl_t *psPeriphCtl = NULL;
- if (!head)
- goto exit_nu_pdma_sg_transfer;
- else if (nu_pdma_check_is_nonallocated(i32ChannID))
- goto exit_nu_pdma_sg_transfer;
- psPeriphCtl = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_spPeripCtl;
- _nu_pdma_transfer(i32ChannID, psPeriphCtl->m_u32Peripheral, head, u32IdleTimeout_us);
- ret = RT_EOK;
- exit_nu_pdma_sg_transfer:
- return -(ret);
- }
- static void nu_pdma_isr(int vector, void *pvdata)
- {
- int i;
- PDMA_T *PDMA = (void *)pvdata;
- uint32_t intsts = PDMA_GET_INT_STATUS(PDMA);
- uint32_t abtsts = PDMA_GET_ABORT_STS(PDMA);
- uint32_t tdsts = PDMA_GET_TD_STS(PDMA);
- uint32_t unalignsts = PDMA_GET_ALIGN_STS(PDMA);
- uint32_t reqto = intsts & PDMA_INTSTS_REQTOFn_Msk;
- uint32_t reqto_ch = (reqto >> PDMA_INTSTS_REQTOFn_Pos);
- int allch_sts = (reqto_ch | tdsts | abtsts | unalignsts);
- // Abort
- if (intsts & PDMA_INTSTS_ABTIF_Msk)
- {
- // Clear all Abort flags
- PDMA_CLR_ABORT_FLAG(PDMA, abtsts);
- }
- // Transfer done
- if (intsts & PDMA_INTSTS_TDIF_Msk)
- {
- // Clear all transfer done flags
- PDMA_CLR_TD_FLAG(PDMA, tdsts);
- }
- // Unaligned
- if (intsts & PDMA_INTSTS_ALIGNF_Msk)
- {
- // Clear all Unaligned flags
- PDMA_CLR_ALIGN_FLAG(PDMA, unalignsts);
- }
- // Timeout
- if (reqto)
- {
- // Clear all Timeout flags
- PDMA->INTSTS = reqto;
- }
- // Find the position of first '1' in allch_sts.
- while ((i = nu_ctz(allch_sts)) < PDMA_CH_MAX)
- {
- int module_id = ((uint32_t)PDMA - DEF_PDMA_BASE_START) / 0x10000UL;
- int j = i + (module_id * PDMA_CH_MAX);
- int ch_mask = (1 << i);
- if (nu_pdma_chn_mask_arr[module_id] & ch_mask)
- {
- int ch_event = 0;
- nu_pdma_chn_t *dma_chn = nu_pdma_chn_arr + j - NU_PDMA_CH_Pos;
- if (dma_chn->m_sCB_Event.m_pfnCBHandler)
- {
- if (abtsts & ch_mask)
- {
- ch_event |= NU_PDMA_EVENT_ABORT;
- }
- if (tdsts & ch_mask)
- {
- ch_event |= NU_PDMA_EVENT_TRANSFER_DONE;
- }
- if (unalignsts & ch_mask)
- {
- ch_event |= NU_PDMA_EVENT_ALIGNMENT;
- }
- if (reqto_ch & ch_mask)
- {
- PDMA_DisableTimeout(PDMA, ch_mask);
- ch_event |= NU_PDMA_EVENT_TIMEOUT;
- }
- if (dma_chn->m_sCB_Disable.m_pfnCBHandler)
- dma_chn->m_sCB_Disable.m_pfnCBHandler(dma_chn->m_sCB_Disable.m_pvUserData, dma_chn->m_sCB_Disable.m_u32Reserved);
- if ((dma_chn->m_u32EventFilter & ch_event) && dma_chn->m_sCB_Event.m_pfnCBHandler)
- dma_chn->m_sCB_Event.m_pfnCBHandler(dma_chn->m_sCB_Event.m_pvUserData, ch_event);
- if (reqto_ch & ch_mask)
- nu_pdma_timeout_set(j, nu_pdma_chn_arr[j - NU_PDMA_CH_Pos].m_u32IdleTimeout_us);
- }//if(dma_chn->handler)
- } //if (nu_pdma_chn_mask & ch_mask)
- // Clear the served bit.
- allch_sts &= ~ch_mask;
- } //while
- }
- static void nu_pdma_memfun_actor_init(void)
- {
- int i = 0 ;
- nu_pdma_init();
- for (i = 0; i < NU_PDMA_MEMFUN_ACTOR_MAX; i++)
- {
- rt_memset(&nu_pdma_memfun_actor_arr[i], 0, sizeof(struct nu_pdma_memfun_actor));
- if (-(RT_ERROR) != (nu_pdma_memfun_actor_arr[i].m_i32ChannID = nu_pdma_channel_allocate(PDMA_MEM)))
- {
- nu_pdma_memfun_actor_arr[i].m_psSemMemFun = rt_sem_create("memactor_sem", 0, RT_IPC_FLAG_FIFO);
- RT_ASSERT(nu_pdma_memfun_actor_arr[i].m_psSemMemFun != RT_NULL);
- }
- else
- break;
- }
- if (i)
- {
- nu_pdma_memfun_actor_maxnum = i;
- nu_pdma_memfun_actor_mask = ~(((1 << i) - 1));
- nu_pdma_memfun_actor_pool_sem = rt_sem_create("mempool_sem", nu_pdma_memfun_actor_maxnum, RT_IPC_FLAG_FIFO);
- RT_ASSERT(nu_pdma_memfun_actor_pool_sem != RT_NULL);
- nu_pdma_memfun_actor_pool_lock = rt_mutex_create("mempool_lock", RT_IPC_FLAG_PRIO);
- RT_ASSERT(nu_pdma_memfun_actor_pool_lock != RT_NULL);
- }
- }
- static void nu_pdma_memfun_cb(void *pvUserData, uint32_t u32Events)
- {
- rt_err_t result = RT_EOK;
- nu_pdma_memfun_actor_t psMemFunActor = (nu_pdma_memfun_actor_t)pvUserData;
- psMemFunActor->m_u32Result = u32Events;
- result = rt_sem_release(psMemFunActor->m_psSemMemFun);
- RT_ASSERT(result == RT_EOK);
- }
- static int nu_pdma_memfun_employ(void)
- {
- int idx = -1 ;
- rt_err_t result = RT_EOK;
- /* Headhunter */
- if (nu_pdma_memfun_actor_pool_sem &&
- ((result = rt_sem_take(nu_pdma_memfun_actor_pool_sem, RT_WAITING_FOREVER)) == RT_EOK))
- {
- RT_ASSERT(result == RT_EOK);
- result = rt_mutex_take(nu_pdma_memfun_actor_pool_lock, RT_WAITING_FOREVER);
- RT_ASSERT(result == RT_EOK);
- /* Find the position of first '0' in nu_pdma_memfun_actor_mask. */
- idx = nu_cto(nu_pdma_memfun_actor_mask);
- if (idx != 32)
- {
- nu_pdma_memfun_actor_mask |= (1 << idx);
- }
- else
- {
- idx = -1;
- }
- result = rt_mutex_release(nu_pdma_memfun_actor_pool_lock);
- RT_ASSERT(result == RT_EOK);
- }
- return idx;
- }
- static rt_size_t nu_pdma_memfun(void *dest, void *src, uint32_t u32DataWidth, unsigned int u32TransferCnt, nu_pdma_memctrl_t eMemCtl)
- {
- nu_pdma_memfun_actor_t psMemFunActor = NULL;
- struct nu_pdma_chn_cb sChnCB;
- rt_err_t result = RT_ERROR;
- int idx;
- rt_size_t ret = 0;
- /* Employ actor */
- while ((idx = nu_pdma_memfun_employ()) < 0);
- psMemFunActor = &nu_pdma_memfun_actor_arr[idx];
- /* Set PDMA memory control to eMemCtl. */
- nu_pdma_channel_memctrl_set(psMemFunActor->m_i32ChannID, eMemCtl);
- /* Register ISR callback function */
- sChnCB.m_eCBType = eCBType_Event;
- sChnCB.m_pfnCBHandler = nu_pdma_memfun_cb;
- sChnCB.m_pvUserData = (void *)psMemFunActor;
- nu_pdma_filtering_set(psMemFunActor->m_i32ChannID, NU_PDMA_EVENT_ABORT | NU_PDMA_EVENT_TRANSFER_DONE);
- nu_pdma_callback_register(psMemFunActor->m_i32ChannID, &sChnCB);
- psMemFunActor->m_u32Result = 0;
- /* Trigger it */
- nu_pdma_transfer(psMemFunActor->m_i32ChannID,
- u32DataWidth,
- (uint32_t)src,
- (uint32_t)dest,
- u32TransferCnt,
- 0);
- /* Wait it done. */
- result = rt_sem_take(psMemFunActor->m_psSemMemFun, RT_WAITING_FOREVER);
- RT_ASSERT(result == RT_EOK);
- /* Give result if get NU_PDMA_EVENT_TRANSFER_DONE.*/
- if (psMemFunActor->m_u32Result & NU_PDMA_EVENT_TRANSFER_DONE)
- {
- ret += u32TransferCnt;
- }
- else
- {
- ret += (u32TransferCnt - nu_pdma_non_transfer_count_get(psMemFunActor->m_i32ChannID));
- }
- /* Terminate it if get ABORT event */
- if (psMemFunActor->m_u32Result & NU_PDMA_EVENT_ABORT)
- {
- nu_pdma_channel_terminate(psMemFunActor->m_i32ChannID);
- }
- result = rt_mutex_take(nu_pdma_memfun_actor_pool_lock, RT_WAITING_FOREVER);
- RT_ASSERT(result == RT_EOK);
- nu_pdma_memfun_actor_mask &= ~(1 << idx);
- result = rt_mutex_release(nu_pdma_memfun_actor_pool_lock);
- RT_ASSERT(result == RT_EOK);
- /* Fire actor */
- result = rt_sem_release(nu_pdma_memfun_actor_pool_sem);
- RT_ASSERT(result == RT_EOK);
- return ret;
- }
- rt_size_t nu_pdma_mempush(void *dest, void *src, uint32_t data_width, unsigned int transfer_count)
- {
- if (data_width == 8 || data_width == 16 || data_width == 32)
- return nu_pdma_memfun(dest, src, data_width, transfer_count, eMemCtl_SrcInc_DstFix);
- return 0;
- }
- void *nu_pdma_memcpy(void *dest, void *src, unsigned int count)
- {
- int i = 0;
- uint32_t u32Offset = 0;
- uint32_t u32Remaining = count;
- for (i = 4; (i > 0) && (u32Remaining > 0) ; i >>= 1)
- {
- uint32_t u32src = (uint32_t)src + u32Offset;
- uint32_t u32dest = (uint32_t)dest + u32Offset;
- if (((u32src % i) == (u32dest % i)) &&
- ((u32src % i) == 0) &&
- (RT_ALIGN_DOWN(u32Remaining, i) >= i))
- {
- uint32_t u32TXCnt = u32Remaining / i;
- if (u32TXCnt != nu_pdma_memfun((void *)u32dest, (void *)u32src, i * 8, u32TXCnt, eMemCtl_SrcInc_DstInc))
- goto exit_nu_pdma_memcpy;
- u32Offset += (u32TXCnt * i);
- u32Remaining -= (u32TXCnt * i);
- }
- }
- if (count == u32Offset)
- return dest;
- exit_nu_pdma_memcpy:
- return NULL;
- }
- /**
- * PDMA memfun actor initialization
- */
- int rt_hw_pdma_memfun_init(void)
- {
- nu_pdma_memfun_actor_init();
- return 0;
- }
- INIT_DEVICE_EXPORT(rt_hw_pdma_memfun_init);
- #endif // #if defined(BSP_USING_PDMA)
|