Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:03

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsARMLPC24XX_dma
0007  *
0008  * @brief Direct memory access (DMA) support.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2008, 2009 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #include <bsp/lpc24xx.h>
0037 #include <bsp/dma.h>
0038 #include <bsp/irq.h>
0039 
0040 static rtems_id lpc24xx_dma_sema_table [GPDMA_CH_NUMBER];
0041 
0042 static bool lpc24xx_dma_status_table [GPDMA_CH_NUMBER];
0043 
0044 static void lpc24xx_dma_copy_handler(void *arg)
0045 {
0046   /* Get interrupt status */
0047   uint32_t tc = GPDMA_INT_TCSTAT;
0048   uint32_t err = GPDMA_INT_ERR_STAT;
0049 
0050   /* Clear interrupt status */
0051   GPDMA_INT_TCCLR = tc;
0052   GPDMA_INT_ERR_CLR = err;
0053 
0054   /* Check channel 0 */
0055   if ((tc & GPDMA_STATUS_CH_0) != 0) {
0056     rtems_semaphore_release(lpc24xx_dma_sema_table [0]);
0057   }
0058   lpc24xx_dma_status_table [0] = (err & GPDMA_STATUS_CH_0) == 0;
0059 
0060   /* Check channel 1 */
0061   if ((tc & GPDMA_STATUS_CH_1) != 0) {
0062     rtems_semaphore_release(lpc24xx_dma_sema_table [1]);
0063   }
0064   lpc24xx_dma_status_table [1] = (err & GPDMA_STATUS_CH_1) == 0;
0065 }
0066 
0067 rtems_status_code lpc24xx_dma_copy_initialize(void)
0068 {
0069   rtems_status_code sc = RTEMS_SUCCESSFUL;
0070   rtems_id id0 = RTEMS_ID_NONE;
0071   rtems_id id1 = RTEMS_ID_NONE;
0072 
0073   /* Create semaphore for channel 0 */
0074   sc = rtems_semaphore_create(
0075     rtems_build_name('D', 'M', 'A', '0'),
0076     0,
0077     RTEMS_LOCAL | RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE,
0078     0,
0079     &id0
0080   );
0081   if (sc != RTEMS_SUCCESSFUL) {
0082     return sc;
0083   }
0084 
0085   /* Create semaphore for channel 1 */
0086   sc = rtems_semaphore_create(
0087     rtems_build_name('D', 'M', 'A', '1'),
0088     0,
0089     RTEMS_LOCAL | RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE,
0090     0,
0091     &id1
0092   );
0093   if (sc != RTEMS_SUCCESSFUL) {
0094     rtems_semaphore_delete(id0);
0095 
0096     return sc;
0097   }
0098 
0099   /* Install DMA interrupt handler */
0100   sc = rtems_interrupt_handler_install(
0101     LPC24XX_IRQ_DMA,
0102     "DMA copy",
0103     RTEMS_INTERRUPT_UNIQUE,
0104     lpc24xx_dma_copy_handler,
0105     NULL
0106   );
0107   if (sc != RTEMS_SUCCESSFUL) {
0108     rtems_semaphore_delete(id0);
0109     rtems_semaphore_delete(id1);
0110 
0111     return sc;
0112   }
0113 
0114   /* Initialize global data */
0115   lpc24xx_dma_sema_table [0] = id0;
0116   lpc24xx_dma_sema_table [1] = id1;
0117 
0118   return RTEMS_SUCCESSFUL;
0119 }
0120 
0121 rtems_status_code lpc24xx_dma_copy_release(void)
0122 {
0123   rtems_status_code sc = RTEMS_SUCCESSFUL;
0124   rtems_status_code rsc = RTEMS_SUCCESSFUL;
0125 
0126   sc = rtems_interrupt_handler_remove(
0127     LPC24XX_IRQ_DMA,
0128     lpc24xx_dma_copy_handler,
0129     NULL
0130   );
0131   if (sc != RTEMS_SUCCESSFUL) {
0132     rsc = sc;
0133   }
0134 
0135   sc = rtems_semaphore_delete(lpc24xx_dma_sema_table [0]);
0136   if (sc != RTEMS_SUCCESSFUL) {
0137     rsc = sc;
0138   }
0139 
0140   sc = rtems_semaphore_delete(lpc24xx_dma_sema_table [1]);
0141   if (sc != RTEMS_SUCCESSFUL) {
0142     rsc = sc;
0143   }
0144 
0145   return rsc;
0146 }
0147 
0148 rtems_status_code lpc24xx_dma_copy(
0149   unsigned channel,
0150   void *dest,
0151   const void *src,
0152   size_t n,
0153   size_t width
0154 )
0155 {
0156   volatile lpc24xx_dma_channel *e = GPDMA_CH_BASE_ADDR(channel);
0157   uint32_t w = GPDMA_CH_CTRL_W_8;
0158 
0159   switch (width) {
0160     case 4:
0161       w = GPDMA_CH_CTRL_W_32;
0162       break;
0163     case 2:
0164       w = GPDMA_CH_CTRL_W_16;
0165       break;
0166   }
0167 
0168   n = n >> w;
0169 
0170   if (n > 0U && n < 4096U) {
0171     e->desc.src = (uint32_t) src;
0172     e->desc.dest = (uint32_t) dest;
0173     e->desc.lli = 0;
0174     e->desc.ctrl = SET_GPDMA_CH_CTRL_TSZ(0, n)
0175       | SET_GPDMA_CH_CTRL_SBSZ(0, GPDMA_CH_CTRL_BSZ_1)
0176       | SET_GPDMA_CH_CTRL_DBSZ(0, GPDMA_CH_CTRL_BSZ_1)
0177       | SET_GPDMA_CH_CTRL_SW(0, w)
0178       | SET_GPDMA_CH_CTRL_DW(0, w)
0179       | GPDMA_CH_CTRL_ITC
0180       | GPDMA_CH_CTRL_SI
0181       | GPDMA_CH_CTRL_DI;
0182     e->cfg = SET_GPDMA_CH_CFG_FLOW(0, GPDMA_CH_CFG_FLOW_MEM_TO_MEM_DMA)
0183       | GPDMA_CH_CFG_IE
0184       | GPDMA_CH_CFG_ITC
0185       | GPDMA_CH_CFG_EN;
0186   } else {
0187     return RTEMS_INVALID_SIZE;
0188   }
0189 
0190   return RTEMS_SUCCESSFUL;
0191 }
0192 
0193 rtems_status_code lpc24xx_dma_copy_wait(unsigned channel)
0194 {
0195   rtems_status_code sc = RTEMS_SUCCESSFUL;
0196 
0197   sc = rtems_semaphore_obtain(
0198     lpc24xx_dma_sema_table [channel],
0199     RTEMS_WAIT,
0200     RTEMS_NO_TIMEOUT
0201   );
0202   if (sc != RTEMS_SUCCESSFUL) {
0203     return sc;
0204   }
0205 
0206   return lpc24xx_dma_status_table [channel]
0207     ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR;
0208 }