Novichok1 0 31 августа, 2009 Опубликовано 31 августа, 2009 · Жалоба Доброго времени суток! Нужно в LPC2478 копировать блоки данных из памяти в память через DMA контроллер. Все делаю, как прописано в мануале: - подаю питание на DMA - енаблю сам DMA - очищаю регистры запросов прерываний на нужном канале - устанавливаю адреса исходных и целевых данных на нужном канале - устанавливаю адрес заранее записанного на флэшку связанного списка - устанавливаю необходимые параметры размеров трансферов - енаблю канал В результате, первый блок копируется нормально, но ко второму элементу связанного списка DMA почему-то не доходит. Я уже не знаю что курить, кто сталкивался с такой проблемой- пожалуйста,поделитесь опытом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Novichok1 0 31 августа, 2009 Опубликовано 31 августа, 2009 · Жалоба Вопрос разрешился - память, куда я записывал список была недоступна для DMA). Странно, что при таком неправильном размещении списка, контроллер DMA не кидал ошибок. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
i.cf 0 31 августа, 2009 Опубликовано 31 августа, 2009 · Жалоба Столкнулся с такой же проблемой! Сейчас стоит LPC2468 ‘-’ Initial device revision (но там вроде с DMA ошибок у них не было). Пробовал для On-chip RAM 0x7FD00000 - 0x7FD03FFF USB RAM (16 kB) и Off-Chip Memory 0xA0000000 - 0xAFFFFFFF Dynamic memory bank 0. Для обоих результат такой-же, как и у Novichok1 - копируется только первый блок, но память-то я разрешенную для использования DMA использую. Ели не сложно - взгляните свежим взглядом - где-то я что-то упускаю... #define MEMORY_SOURCE 0x7FD00000 #define MEMORY_DESTINATION 0x7FD01000 #define TRANSFER_SIZE 16 int main(void) { volatile unsigned int chain_arr[3][4]; unsigned char *temp1_ptr; unsigned char *temp2_ptr; unsigned int i; // set buffers temp1_ptr = (U8*)MEMORY_SOURCE; temp2_ptr = (U8*)MEMORY_DESTINATION; for (i = 0; i < 200; ++i) { temp1_ptr[i] = i; temp2_ptr[i] = 0; } // set chain list chain_arr[0][0] = MEMORY_SOURCE; chain_arr[0][1] = MEMORY_DESTINATION; chain_arr[0][2] = (unsigned int)&chain_arr[1][0]; chain_arr[0][3] = (TRANSFER_SIZE & 0x0FFF)//set the transfer size | (1u << 12) //Source burst size | (1u << 15) //destination burst size | (0u << 18) //Source width | (0u << 21) //destination width | (1u << 26) //Source increment | (1u << 27) //Destination increment | (0u << 31); //interrupt chain_arr[1][0] = MEMORY_SOURCE + 32; chain_arr[1][1] = MEMORY_DESTINATION + 32; chain_arr[1][2] = (unsigned int)&chain_arr[2][0]; chain_arr[1][3] = (TRANSFER_SIZE & 0x0FFF)//set the transfer size | (1u << 12) //Source burst size | (1u << 15) //destination burst size | (0u << 18) //Source width | (0u << 21) //destination width | (1u << 26) //Source increment | (1u << 27) //Destination increment | (0u << 31); //interrupt chain_arr[2][0] = MEMORY_SOURCE + 64; chain_arr[2][1] = MEMORY_DESTINATION + 64; chain_arr[2][2] = 0; chain_arr[2][3] = (TRANSFER_SIZE & 0x0FFF)//set the transfer size | (1u << 12) //Source burst size | (1u << 15) //destination burst size | (0u << 18) //Source width | (0u << 21) //destination width | (1u << 26) //Source increment | (1u << 27) //Destination increment | (1u << 31); //interrupt // enable GPDMA PCONP |= (0x1<<29); // Power up the GPDMA GPDMA_CONFIG = 0x01; // Enable the GPDMA while (!(GPDMA_CONFIG & 0x01)); // Wait until the GPDMA is operational // configure and start GPDMA GPDMA_INT_TCCLR = 0x01; // Clear the interrupt status bits GPDMA_INT_ERR_CLR = 0x01; GPDMA_CH0_SRC = chain_arr[0][0]; // Load source start address into Channel 0 GPDMA_CH0_DEST = chain_arr[0][1]; // Load destination start address into Channel 0 GPDMA_CH0_CTRL = chain_arr[0][3]; //set the transfer size and settings GPDMA_CH0_LLI = chain_arr[0][2]; // next item to transfer GPDMA_CH0_CFG |= 0x08001; // Start the channel transfer while (!GPDMA_RAW_INT_TCSTAT); //Wait until the transfer has finished for(;;); return 0; } Список вроде правильный формируется : Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
i.cf 0 2 сентября, 2009 Опубликовано 2 сентября, 2009 (изменено) · Жалоба Так мне и не удалось по-нормальному запустить DMA... Пытался запустить пример к книге The insiders guide to the NXP LPC2300 2400 Based Microcontrollers. Для запуска под keil пришлось: - добавить объявление unsigned int *Buffer1,*Buffer2; - заменить GPDMA_CH0_LLI = (unsigned int *) item1; на GPDMA_CH0_LLI = (unsigned int) item1; В результате - все как и раньше - копируется только первый блок из 0x7FD00000 в 0x7FD00500, а уже из 0x7FD00000 в 0x7FD00600 копирования не происходит... Ну и ес-но виснет на while ( !GPDMA_RAW_INT_CSTAT ); #include "lpc230x.h" #define DMA_SRC 0x7FD00000 #define DMA_DST 0x7FD00500 #define DMA_SIZE 0x100 unsigned int i; unsigned int *Buffer1,*Buffer2; volatile unsigned int item1[4] = {0x7FD00000,0x7FD00600,0,0x8C4A4000}; int main (void) { T0TCR = 0x00000002; //Reset counter and prescaler Buffer1 = (unsigned int *)DMA_SRC; //Set the start address of the source buffer Buffer2 = (unsigned int *)DMA_DST; //Set the start address of the destination buffer for ( i = 0; i < DMA_SIZE/4; i++ ) //Initilise the buffers { *Buffer1 = i; *Buffer2 = 0; Buffer1++; Buffer2++; } PCONP |= (0x1<<29); // Power up the GPDMA GPDMA_CONFIG = 0x01; // Enable the GPDMA while ( !(GPDMA_CONFIG & 0x01) ); // Wait until the GPDMA is operational GPDMA_INT_CCLR = 0x01; //Clear the interrupt status bits GPDMA_INT_ERR_CLR = 0x01; GPDMA_CH0_SRC = DMA_SRC; //Load buffer1 start address into Channel 0 GPDMA_CH0_DEST = DMA_DST; //Load buffer2 start address into Channel0 GPDMA_CH0_CTRL = ((DMA_SIZE/4) & 0x0FFF) //set the transfer size | (0x04 << 12) // Source burst size | (0x04 << 15) //destination burst size | (0x02 << 18) //Source width | (0x02 << 21) //destination width | (1 << 26) //Source increment | (1 << 27) //Destination increment | (0<<31); //Enable the terminal count interrupt GPDMA_CH0_LLI = (unsigned int) item1; T0TCR = 0x00000001; //enable timer GPDMA_CH0_CFG |= 0x08001; //Start the channel zero transfer while ( !GPDMA_RAW_INT_CSTAT ); //Wait until the transfer has finished T0TCR = 0x00000000; //disable timer T0TCR = 0x00000002; //Reset counter and prescaler while(1) { ; } return (0); } Пробовал массив размещать в "разрешенной" для DMA памяти - по адресу 0x7FD00700 - результат тот-же... Что нужно сделать, что б заставить копировать несколько блоков? Может у кого-то есть работающий пример? Изменено 2 сентября, 2009 пользователем i.cf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
i.cf 0 17 сентября, 2009 Опубликовано 17 сентября, 2009 · Жалоба Мда... Судя по обилию ответов, за более чем двухлетнее существование семейства, с List в DMA так никто и не работал... :unsure: Выкладываю рабочий пример для будущих поколений. example1.zip Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 4 октября, 2009 Опубликовано 4 октября, 2009 · Жалоба Был бы смысл в копировании память-память, мож кто бы и работал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
i.cf 0 5 октября, 2009 Опубликовано 5 октября, 2009 (изменено) · Жалоба Был бы смысл в копировании память-память, мож кто бы и работал. Немало дополнительной периферии подключают через контроллер внешней памяти. Причем объемы данных, которые приходится гонять подчас оказываются не малыми. Тут-то как раз и есть смысл использовать DMA для копирования память-память. Изменено 5 октября, 2009 пользователем i.cf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Novichok1 0 9 октября, 2009 Опубликовано 9 октября, 2009 · Жалоба Также есть смысл при реализации буферизации дисплея, более чем одного порядка. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Quasar 20 1 марта, 2010 Опубликовано 1 марта, 2010 (изменено) · Жалоба Столкнулся с проблемой, не получается запустить DMA на LPC2478 и LPC2378. Не хочет работать с SSP1, хотя с SSP0 работает нормально. Причем ошибки в инициализации SSP нет, так как при работе SSP1 с такой же конфигурацией но без DMA, все ok. char dma_src[sSP_BUFSIZE] __attribute__((at(0x7FD00000))); char dma_dst[sSP_BUFSIZE] __attribute__((at(0x7FD01000))); static DWORD SSP1Init( void ) { BYTE i, Dummy = Dummy; /* enable clock to SSP1 for security reason. By default, it's enabled already */ PCONP |= (1 << 10); PINSEL0 &= !( 0xFF << 12 ); PINSEL0 |= ( 0xAA << 12 ); /* Set DSS data to 8-bit, Frame format SPI, CPOL = 0, CPHA = 0, and SCR is 15 */ SSP1CR0 = 0x0707; /* SSPCPSR clock prescale register, master mode, minimum divisor is 0x02 */ #if LOOPBACK_MODE SSP1CPSR = 0x2; #else /* Much slower clock is needed in order to test serial EEPROM. */ SSP1CPSR = 0x40; #endif for ( i = 0; i < FIFOSIZE; i++ ) { Dummy = SSP1DR; /* clear the RxFIFO */ } if ( install_irq( SSP1_INT, (void *)SSP1Handler, HIGHEST_PRIORITY ) == FALSE ) { return (FALSE); } /* Device select as master, SSP Enabled */ #if LOOPBACK_MODE SSP1CR1 = SSPCR1_LBM | SSPCR1_SSE; #else SSP1CR1 = SSPCR1_SSE; #endif /* Set SSPINMS registers to enable interrupts */ /* enable all error related interrupts */ SSP1IMSC = SSPIMSC_RORIM | SSPIMSC_RTIM; return( TRUE ); } /***************************************************************************** ** Function name: LoopbackTest ** ** Descriptions: Loopback test ** ** parameters: None ** Returned value: None ** *****************************************************************************/ void DMATest( void ) { DWORD i; volatile DWORD cnt; PCONP |= (1 << 29); /* Enable GPDMA clock */ /* Ch0 set for M2P transfer from mempry to SSP1. */ GPDMA_CH0_SRC = (unsigned long)dma_src; GPDMA_CH0_DEST = SSP1DR; /* The burst size is set to 8, the size is 8 bit too. */ /* Terminal Count Int enable */ GPDMA_CH0_CTRL = (SSP_BUFSIZE & 0x0FFF) | (0x02 << 12) | (0x02 << 15) | (0x01 << 26) | 0x80000000; GPDMA_CH0_CFG = (0x01 << 16) /* Lock bit */ | (0x01 << 15) /* Terminal count interrupt mask. */ | (0x05 << 11) /* Flow control and transfer type. M2P*/ | (0x00 << 6 ) /* Destination peripheral. */ | (0x02 << 1 ) /* SSP1 Tx. */ | (0x01 << 0 ); /* Channel enabled. */ /* Ch1 set for P2M transfer from SSP1 to memory. */ GPDMA_CH1_SRC = SSP1DR; GPDMA_CH1_DEST = (unsigned long)dma_dst; /* The burst size is set to 8, the size is 8 bit too. */ /* Terminal Count Int enable */ GPDMA_CH1_CTRL = (SSP_BUFSIZE & 0x0FFF) | (0x02 << 12) | (0x02 << 15) | (0x01 << 27) | 0x80000000; GPDMA_CH1_CFG = (0x01 << 16) /* Lock bit */ | (0x01 << 15) /* Terminal count interrupt mask. */ | (0x06 << 11) /* Flow control and transfer type. P2M*/ | (0x00 << 6 ) /* Destination peripheral. */ | (0x03 << 1 ) /* SSP1 Rx. */ | (0x01 << 0 ); /* Channel enabled. */ GPDMA_CONFIG = 0x01; /* Enable DMA channels, little endian */ while ( !(GPDMA_CONFIG & 0x01) ); if ( install_irq( GPDMA_INT, (void *)DMAHandler, HIGHEST_PRIORITY ) == FALSE ) { while (1) /* PANIC */; } /* Enable DMA TX and RX on SSP1 */ SSP1DMACR = 0x03; cnt = 0x10000; while ( cnt-- ) ; /* verifying, ignore the difference in the first two bytes */ for ( i = 0; i < SSP_BUFSIZE; i++ ){ if ( dma_dst[i] != dma_src[i] ){ while (1) /* PANIC */; /* Verification failed */ } } return; } void SSP1Send( BYTE *buf, DWORD Length ) { DWORD i; BYTE Dummy = Dummy; for ( i = 0; i < Length; i++ ) { /* Move on only if NOT busy and TX FIFO not full. */ while ( (SSP1SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF ); SSP1DR = *buf; buf++; #if !LOOPBACK_MODE while ( (SSP1SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE ); /* Whenever a byte is written, MISO FIFO counter increments, Clear FIFO on MISO. Otherwise, when SSP0Receive() is called, previous data byte is left in the FIFO. */ Dummy = SSP1DR; #else /* Wait until the Busy bit is cleared. */ while ( SSP1SR & SSPSR_BSY ); #endif } return; } /****************************************************************************** ** Main Function main() ******************************************************************************/ int main (void) { DWORD i; SSP1Init(); while (1) { for ( i = 0; i < SSP_BUFSIZE; i++ ) { dma_src[i] = 0xAA; dma_dst[i] = 0x00; } DMATest(); //SSP1Send( ((BYTE *)DMA_SRC), SSP_BUFSIZE ); } } Изменено 20 марта, 2011 пользователем IgorKossak codebox тег для оформления длинного кода Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexandermas 0 20 марта, 2011 Опубликовано 20 марта, 2011 · Жалоба Мда... Судя по обилию ответов, за более чем двухлетнее существование семейства, с List в DMA так никто и не работал... :unsure: Выкладываю рабочий пример для будущих поколений. по поводу связанных списков. может уже и ненадо но все равно напишу. дма контроллер вистит наглухо при использовании списков и режима передач big - endian. т. е. если его переключить в другой режим все становится на свои места и начинает работать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться