|
|
 |
Ответов
(1 - 9)
|
Aug 31 2009, 09:40
|
Участник

Группа: Участник
Сообщений: 73
Регистрация: 8-07-09
Пользователь №: 51 032

|
Вопрос разрешился - память, куда я записывал список была недоступна для DMA). Странно, что при таком неправильном размещении списка, контроллер DMA не кидал ошибок.
|
|
|
|
|
Aug 31 2009, 23:40
|

Участник

Группа: Участник
Сообщений: 56
Регистрация: 25-08-09
Из: Украина, Харьков
Пользователь №: 52 034

|
Столкнулся с такой же проблемой! Сейчас стоит 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 использую. Ели не сложно - взгляните свежим взглядом - где-то я что-то упускаю... CODE #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; } Список вроде правильный формируется :
Причина редактирования: Уменьшение видимого размера цитаты исходника.
|
|
|
|
|
Sep 2 2009, 18:57
|

Участник

Группа: Участник
Сообщений: 56
Регистрация: 25-08-09
Из: Украина, Харьков
Пользователь №: 52 034

|
Так мне и не удалось по-нормальному запустить 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 );CODE #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 - результат тот-же... Что нужно сделать, что б заставить копировать несколько блоков? Может у кого-то есть работающий пример?
Сообщение отредактировал i.cf - Sep 2 2009, 19:13
|
|
|
|
|
Sep 17 2009, 10:18
|

Участник

Группа: Участник
Сообщений: 56
Регистрация: 25-08-09
Из: Украина, Харьков
Пользователь №: 52 034

|
Мда... Судя по обилию ответов, за более чем двухлетнее существование семейства, с List в DMA так никто и не работал... Выкладываю рабочий пример для будущих поколений.
|
|
|
|
|
Oct 5 2009, 14:18
|

Участник

Группа: Участник
Сообщений: 56
Регистрация: 25-08-09
Из: Украина, Харьков
Пользователь №: 52 034

|
Цитата(DpInRock @ Oct 4 2009, 11:40)  Был бы смысл в копировании память-память, мож кто бы и работал. Немало дополнительной периферии подключают через контроллер внешней памяти. Причем объемы данных, которые приходится гонять подчас оказываются не малыми. Тут-то как раз и есть смысл использовать DMA для копирования память-память.
Сообщение отредактировал i.cf - Oct 5 2009, 14:19
|
|
|
|
|
Oct 9 2009, 03:18
|
Участник

Группа: Участник
Сообщений: 73
Регистрация: 8-07-09
Пользователь №: 51 032

|
Также есть смысл при реализации буферизации дисплея, более чем одного порядка.
|
|
|
|
|
Mar 1 2010, 19:44
|

Местный
  
Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021

|
Столкнулся с проблемой, не получается запустить DMA на LPC2478 и LPC2378. Не хочет работать с SSP1, хотя с SSP0 работает нормально. Причем ошибки в инициализации SSP нет, так как при работе SSP1 с такой же конфигурацией но без DMA, все ok. CODE 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 ); }
}
Сообщение отредактировал IgorKossak - Mar 20 2011, 14:59
Причина редактирования: codebox тег для оформления длинного кода
|
|
|
|
|
Mar 20 2011, 10:47
|
Участник

Группа: Участник
Сообщений: 15
Регистрация: 13-07-10
Пользователь №: 58 429

|
Цитата(i.cf @ Sep 17 2009, 14:18)  Мда... Судя по обилию ответов, за более чем двухлетнее существование семейства, с List в DMA так никто и не работал... :unsure:
Выкладываю рабочий пример для будущих поколений. по поводу связанных списков. может уже и ненадо но все равно напишу. дма контроллер вистит наглухо при использовании списков и режима передач big - endian. т. е. если его переключить в другой режим все становится на свои места и начинает работать
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|