Changeset 657 for trunk/hal/tsar_mips32/drivers/soclib_dma.c
- Timestamp:
- Mar 18, 2020, 11:16:59 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/hal/tsar_mips32/drivers/soclib_dma.c
r570 r657 2 2 * soclib_dma.c - soclib Multi Channels DMA driver implementation 3 3 * 4 * Author Alain Greiner (2017 )4 * Author Alain Greiner (2017,2018,2019,2020) 5 5 6 6 * Copyright (c) UPMC Sorbonne Universites … … 39 39 chdev->isr = &soclib_dma_isr; 40 40 41 // enable interrupts42 hal_remote_s32( XPTR( dma_cxy , dma_ptr + DMA_IRQ_DISABLED ) , 0);41 // disable interrupts 42 hal_remote_s32( XPTR( dma_cxy , dma_ptr + DMA_IRQ_DISABLED ) , 1 ); 43 43 44 44 } // soclib_dma_init() … … 47 47 void __attribute__ ((noinline)) soclib_dma_cmd( xptr_t thread_xp ) 48 48 { 49 bool_t sync; 49 50 xptr_t dev_xp; // extended pointer on DMA devive 50 51 xptr_t dst_xp; // extended pointer on destination buffer 51 52 xptr_t src_xp; // extended pointer on source buffer 52 53 uint32_t size; // buffer size 54 uint32_t status; // DMA status 53 55 54 56 // get client thread cluster and local pointer 55 cxy_t thread_cxy = GET_CXY( thread_xp ); 56 thread_t * thread_ptr = (thread_t *)GET_PTR( thread_xp ); 57 58 // get command arguments and extended pointer on DMA device 59 dev_xp = (xptr_t)hal_remote_l64( XPTR( thread_cxy , &thread_ptr->dma_cmd.dev_xp ) ); 60 dst_xp = (xptr_t)hal_remote_l64( XPTR( thread_cxy , &thread_ptr->dma_cmd.dst_xp ) ); 61 src_xp = (xptr_t)hal_remote_l64( XPTR( thread_cxy , &thread_ptr->dma_cmd.src_xp ) ); 62 size = hal_remote_l32 ( XPTR( thread_cxy , &thread_ptr->dma_cmd.size ) ); 57 cxy_t client_cxy = GET_CXY( thread_xp ); 58 thread_t * client_ptr = (thread_t *)GET_PTR( thread_xp ); 59 60 #if (DEBUG_HAL_IOC_RX || DEBUG_HAL_IOC_TX) 61 uint32_t cycle = (uint32_t)hal_get_cycles(); 62 thread_t * this = CURRENT_THREAD; 63 process_t * process = hal_remote_lpt( XPTR( th_cxy , &th_ptr->process ) ); 64 pid_t client_pid = hal_remote_l32( XPTR( th_cxy , &process->pid ) ); 65 trdid_t client_trdid = hal_remote_l32( XPTR( th_cxy , &th_ptr->trdid ) ); 66 #endif 67 68 // TODO both the client and the server threads are allways local, 69 // we could replace all these remote accesses by local accesses !!! [AG] 70 71 // get command arguments and extended pointer on DMA device descriptor 72 sync = hal_remote_l32( XPTR( client_cxy , &client_ptr->dma_cmd.sync ) ); 73 dev_xp = (xptr_t)hal_remote_l64( XPTR( client_cxy , &client_ptr->dma_cmd.dev_xp ) ); 74 dst_xp = (xptr_t)hal_remote_l64( XPTR( client_cxy , &client_ptr->dma_cmd.dst_xp ) ); 75 src_xp = (xptr_t)hal_remote_l64( XPTR( client_cxy , &client_ptr->dma_cmd.src_xp ) ); 76 size = hal_remote_l32( XPTR( client_cxy , &client_ptr->dma_cmd.size ) ); 63 77 64 78 // get DMA device cluster and local pointer … … 66 80 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 67 81 68 // get extended pointer on SOCLIB-DMA peripheral 69 xptr_t dma_xp = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->base ) ); 70 71 // get SOCLIB_DMA device cluster and local pointer 82 // get pointers on DMA peripheral 83 xptr_t dma_xp = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->base ) ); 72 84 cxy_t dma_cxy = GET_CXY( dma_xp ); 73 uint32_t * dma_ptr = (uint32_t *)GET_PTR( dma_xp );85 uint32_t * dma_ptr = GET_PTR( dma_xp ); 74 86 75 87 // get DMA channel index and channel base address … … 82 94 uint32_t src_msb = (uint32_t)(src_xp>>32); 83 95 84 // set SOCLIB_DMA registers to starttranfer operation96 // set SOCLIB_DMA registers and launch tranfer operation 85 97 hal_remote_s32( XPTR( dma_cxy , base + DMA_SRC ) , src_lsb ); 86 98 hal_remote_s32( XPTR( dma_cxy , base + DMA_SRC_EXT ) , src_msb ); 87 99 hal_remote_s32( XPTR( dma_cxy , base + DMA_DST ) , dst_lsb ); 88 100 hal_remote_s32( XPTR( dma_cxy , base + DMA_DST_EXT ) , dst_msb ); 89 hal_remote_s32( XPTR( dma_cxy , base + DMA_LEN ) , size ); 90 91 // Block and deschedule server thread 92 thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_ISR ); 93 sched_yield("blocked on ISR"); 94 101 hal_remote_s32( XPTR( dma_cxy , base + DMA_LEN_STS ) , size ); 102 103 #if DEBUG_HAL_DMA 104 if( DEBUG_HAL_DMA < cycle ) 105 printk("\n[%s] thread[%x,%x] launched DMA for client thread[%x,%x] / cycle %d\n", 106 __FUNCTION__, this->process->pid, this->trdid, client_pid, client_trdid, cycle ); 107 #endif 108 109 // waiting policy depends on the command type 110 // - for an asynchronous command, this function is called by the server thread 111 // => block and deschedule after launching the transfer. 112 // The operation status is reported in the command by the ISR, and the 113 // server thread is re-activated by the ISR. 114 // - for a synchronous command, this function is called by the client thread 115 // => mask the DMA_IRQ and poll the DMA status register until transfer completion, 116 // and reports status in the command when the transfer is completed. 117 118 if( sync ) // client thread poll status until completion 119 { 120 while( 1 ) 121 { 122 status = hal_remote_l32( XPTR( dma_cxy , base + DMA_LEN_STS ) ); 123 124 if( (status == DMA_SUCCESS) || (status == DMA_IDLE) ) 125 { 126 // set operation status in command 127 hal_remote_s32( XPTR( client_cxy , &client_ptr->dma_cmd.error ) , 0 ); 128 129 #if DEBUG_HAL_DMA 130 cycle = (uint32_t)hal_get_cycles(); 131 if( DEBUG_HAL_DMA < cycle ) 132 printk("\n[%s] thread[%x,%x] exit after SYNC success / cycle %d\n", 133 __FUNCTION__, this->process->pid, this->trdid, cycle ); 134 #endif 135 // exit while 136 break; 137 } 138 else if( (status == DMA_ERROR_READ) || (status == DMA_ERROR_WRITE) ) 139 { 140 // set operation status in command 141 hal_remote_s32( XPTR( client_cxy , &client_ptr->dma_cmd.error ) , 1 ); 142 143 #if DEBUG_HAL_DMA 144 cycle = (uint32_t)hal_get_cycles(); 145 if( DEBUG_HAL_DMA < cycle ) 146 printk("\n[%s] thread[%x,%x] exit after SYNC failure / cycle %d\n", 147 __FUNCTION__, this->process->pid, this->trdid, cycle ); 148 #endif 149 // exit while 150 break; 151 } 152 } 153 } 154 else // server thread block and deschedule 155 { 156 // server thread blocks on ISR 157 thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_ISR ); 158 159 // enable DMA interrupts 160 hal_remote_s32( XPTR( dma_cxy , dma_ptr + DMA_IRQ_DISABLED ) , 0 ); 161 162 // server thread deschedules 163 sched_yield("blocked on ISR"); 164 165 // disable DMA interrupts 166 hal_remote_s32( XPTR( dma_cxy , dma_ptr + DMA_IRQ_DISABLED ) , 1 ); 167 168 #if DEBUG_HAL_DMA 169 cycle = (uint32_t)hal_get_cycles(); 170 if( DEBUG_HAL_DMA < cycle ) 171 printk("\n[%s] thread[%x,%x] exit after ASYNC / client thread[%x,%x] / cycle %d\n", 172 __FUNCTION__ , this->process->pid, this->trdid, client_pid, client_trdid, cycle ); 173 #endif 174 175 } 95 176 } // soclib_dma_cmd() 96 177 … … 98 179 void __attribute__ ((noinline)) soclib_dma_isr( chdev_t * chdev ) 99 180 { 100 // get extended pointer on client thread 181 // get extended pointer on server thread 182 xptr_t server_xp = XPTR( local_cxy , &chdev->server ); 183 184 // get extended pointer on client thread 101 185 xptr_t root = XPTR( local_cxy , &chdev->wait_root ); 102 186 xptr_t client_xp = XLIST_FIRST( root , thread_t , wait_list ); 103 104 // get extended pointer on server thread105 xptr_t server_xp = XPTR( local_cxy , &chdev->server );106 187 107 188 // get client thread cluster and local pointer … … 113 194 uint32_t * dma_ptr = (uint32_t *)GET_PTR( chdev->base ); 114 195 115 // getDMA channel base address196 // build DMA channel base address 116 197 uint32_t * base = dma_ptr + (DMA_SPAN * chdev->channel); 117 198 118 199 // get DMA status register 119 uint32_t status = hal_remote_l32( XPTR( dma_cxy , base + DMA_LEN ) );200 uint32_t status = hal_remote_l32( XPTR( dma_cxy , base + DMA_LEN_STS ) ); 120 201 121 202 // acknowledge IRQ … … 129 210 thread_unblock( server_xp , THREAD_BLOCKED_ISR ); 130 211 131 // unblock client thread132 thread_unblock( client_xp , THREAD_BLOCKED_IO );133 134 212 } // soclib_dma_isr() 135 213
Note: See TracChangeset
for help on using the changeset viewer.