DMA controller on Ti 8051

Thread Starter

PhotoMonger

Joined Jan 7, 2008
16
Hello,
I'm using the TiCC2430 which has an 8051 core and DMA controller. I have set up the ADC to read a series of samples from it's inputs. The samples should be transfered to memory via the DMA controller. When I go to check the values it appears the transfer has not occured. I get an EOC flag for the ADC and an Interrupt from the DMA so I think the conversion and moving of data is working.

I think that I'm looking in the wrong place. I have set the data to be transfered to address 0x0004. When I check XData in IAR Workbench i don't see the correct answer.

Let me know if you want to see my configuration registers.
Thanks.
 

Papabravo

Joined Feb 24, 2006
21,228
0x0004 is an ambiguous address in the 8051 architecture.
It could refer to 0x0004 in external data memory. If RD* and WR* are active during the access then it's external data memory. Normally the processor makes this access when using either form of the MOVX instruction.

It could be 0x0004 in code space although that seems unlikely in this context.

It could be 0x04 in internal RAM which would overwrite the registers for bank 0.

We were never able to integrate a DMA with an 8051 because there is no way to interleave bus cycles, since the processor has no request-grant mechanism, and there is no way to hold the processor off from a memory access when it wants to make one. If you got it working you must have some powerful mojo. If the core is static the only way you can do this is to stop the clock. That kinda defeats the purpose of DMA so we consider it cheating.
 

Thread Starter

PhotoMonger

Joined Jan 7, 2008
16
ok, I got it work late last night. I had to use a different destination address. I chose the address by looking for an empty memory space in XDATA before the DMA command. Obviously this is a major hack and probably won't work under normal operations. Where can I find information on the adress space so I can find an appropriate place to store this info? My other option would be to write it directly to the SOC's flash. I'm not sure this is possible.
 

Thread Starter

PhotoMonger

Joined Jan 7, 2008
16
0x0004 is an ambiguous address in the 8051 architecture.
It could refer to 0x0004 in external data memory. If RD* and WR* are active during the access then it's external data memory. Normally the processor makes this access when using either form of the MOVX instruction.

It could be 0x0004 in code space although that seems unlikely in this context.

It could be 0x04 in internal RAM which would overwrite the registers for bank 0.
cheating.
How do I determine I'd RD* or WR* are active?
this has to be possible, why would they include this function if it were not?
 

Papabravo

Joined Feb 24, 2006
21,228
In the 8051 core architecture the only way to activate RD* is to execute a MOVX A,@DPTR instruction or it's little brothers MOVX A,@R0 or MOVX A,@R1

The only way to activate WR* is to execute a MOVX @DPTR,A or one of it's little brothers MOVX @R0,A or MOVX @R1,A. These signals must be routed to any XDATA memory which is implemented on the chip. XDATA can be up to 64K bytes long.

Hoe do you determine if they are active? Iguess you put a probe on them or run the simulation in such a way that you can observe them.

How do you get a DMA controller to arbitrate with the processor for control of these signal? Beats the pure hell outta me -- I don't think it can be done without using a dual port memory for part of XDATA.
 

Thread Starter

PhotoMonger

Joined Jan 7, 2008
16
Ok, here is how you do it.
Papabravo, looks liek I do have the MOJO ;)


uint8* HalAdcReadSeries (uint8 channel, uint8 resolution)
{
uint8 *location = buffer;

#if (HAL_ADC == TRUE)

uint8 i,resbits;
bool complete = FALSE;
volatile uint8 tmp;
/* When doing multple consecutive ADC samples we must use the DMA controller to transfer the samples
* from the ADC registers into XDATA.
*/

ADCCFG |= 0xFF; //Set all PO pins to ADC inputs
ADCCON1 = HAL_ADC_STSEL | HAL_ADC_RAND_STOP | 0x03;
ADCCON3 = 0x05; //For some reson the last 4 bits of ADCCON2 can only be written by writing to ADCCON3
HAL_ADC_CLR_EOC(); //Writing to ADCCON3 will initiate a sample so we must clear the EOC bit to start our series sampling
ADCCON2 = HAL_ADC_REF_AVDD | HAL_ADC_DEC_RATE | 0x05;

switch (resolution)
{
case HAL_ADC_RESOLUTION_8:
resbits = HAL_ADC_DEC_064;
break;
case HAL_ADC_RESOLUTION_10:
resbits = HAL_ADC_DEC_128;
break;
case HAL_ADC_RESOLUTION_12:
resbits = HAL_ADC_DEC_256;
break;
case HAL_ADC_RESOLUTION_14:
default:
resbits = HAL_ADC_DEC_512;
break;
}

halDMADesc_t *ch;
ch = HAL_DMA_GET_DESC1234(3); //Use DMA3 channel3 as adc storage
HAL_DMA_SET_DEST(ch,buffer);
if(resolution == HAL_ADC_RESOLUTION_8) //Just read transfer most sig byte to XDATA
{
HAL_DMA_SET_SOURCE(ch,0xDFBB);
HAL_DMA_SET_WORD_SIZE(ch,0x00); //Trnsfer a 8-bit byte at a time
}
else //Transfer both bytes to XDATA
{
HAL_DMA_SET_SOURCE(ch,0xDFBA);
HAL_DMA_SET_WORD_SIZE(ch,0x01); //Trnsfer a 8-bit byte at a time
}

for(i=0; i<100; i++)
{
asm("NOP");
}

//Arm DMA for sampeling
HAL_DMA_CLEAR_IRQ(3);
HAL_DMA_ARM_CH(3);

/*Start a conversion by setting ADCCON1.ST=1*/
ADCCON1 |= 0x40;

/* Wait for the conversion to be done indicated by ADCCON1.ST=0 */
while(!(HAL_DMA_CHECK_IRQ(3)));

//Disable ADC channes since the EM uses them for other things
ADCCFG &= ~0xFF; //If we turn off the I/O ports our sample won't complete

#endif
return(location);
}

Cheers,
Ian
 

Papabravo

Joined Feb 24, 2006
21,228
Never start vast projects with half vast ideas!

DMA? -- well sorta half vast DMA. The "do nothing" loop of 100 NOP instructions guarantees that the processor will not compete with the DMA controller for access to XDATA memory. If that's your solution then let me give you a big fat raspberry (pthwaaaat!) for setting up a straw man and knocking it down.

In case you are unaware of the reason for having a DMA in the first place it is for the purpose of overlapping the I/O transfer with other processing. Having to avoid reference to XDATA while DMA is in progress is a fairly severe restriction. After you add the setup and the overhead wouldn't it be simpler to just read the A/D converter instead of jumping through hoops?

Maybe this was just a practice project to see if you could do it.
 

Thread Starter

PhotoMonger

Joined Jan 7, 2008
16
Ouch, a bit harsh don't you think. Why would they have this ADC to DMA feature if you couldn't use it. This is how I got it to work for now. If I wanted to minimize processor interaction I could set upan ISR to process when the DMA flag is set.
 

Papabravo

Joined Feb 24, 2006
21,228
I can't answer that question. Just because a feature is provided doesn't mean it is necessarily a good idea. Let me be clear about what I'm attacking here -- its the idea and NOT the people. It is DMA in the snese that by cooperating, two processors (CPU and DMA controller) may have access to the same memory. This is the same sense in which Windows originally claimed to be a multitasking OS because the tasks cooperated by voluntarily relinquishing control. That works well doesn't it.

My argument here has to do with the restrictions imposed in exchange for the "alleged" benefit. Personally for an A/D converter I'd rather construct a simple processor based scheme for handling such a small amount of data. If we are talking large amounts of data at very high speeds then perhaps I could be persuaded of the benefit of incurring the overhead of setting up and running a DMA controller. On an 8051 without the hardware required to request and grant the memory bus it seems limited.
 
Top