Jump to content
M-atthias

Discovered TM4C1294 ADC silicon bug ?

Recommended Posts

Dear Stellaris geeks,

I am porting code from LM4F120 Stellaris Launchpad to TM4C1294 Tiva Connected Launchpad. I found the literature SPMA065 "Differences Between Tiva C Series TM4C Microcontrollers" which states that analog-digital converters in TM4C1294 only add features relative to TM4C123 / LM4F120.

But I cannot make my ADC code work. To nail it down I have done this minimal example code in Forth (Mecrisp-Stellaris 1.1.5):

$400FE638 constant RCGCADC

: init-analog ( -- )
  $1 RCGCADC ! \ Provide clock to AD-Converter
               \ PIOs already activated in Core
  50 0 do loop \ Wait a bit
;

$40038000 constant ADC0_ACTSS
$40038044 constant ADC0_SSCTL0
$40038028 constant ADC0_PSSI
$40038048 constant ADC0_SSFIFO0

: temperature ( -- Measurement )

  0 ADC0_ACTSS !   \ Disable Sample Sequencers
 $A ADC0_SSCTL0 !  \ First Sample is from Temperature Sensor and End of Sequence
  1 ADC0_ACTSS !   \ Enable Sample Sequencer 0
  1 ADC0_PSSI !    \ Initiate sampling

  begin $10000 ADC0_ACTSS bit@ not until \ Check busy Flag for ADC

  ADC0_SSFIFO0 @ \ Fetch measurement result
;

init-analog temperature .

This runs fine on LM4F120, but it hangs in busy loop on TM4C1294. Further research shows that ACTSS busy flag is never cleared again, this register always reads $00010001 after setting the bit in PSSI register (it is $00000001 before setting PSSI bit). This behaviour happens to all other analog input channels, too, but temperature sensor gives shortest code.

Setting SSCTL0 Interrupt Enable together with Temperature and End of Sequence flag doesn't generate a bit in RIS register either.

I am puzzled, perhaps this is a silicon bug undocumented in current chip errata ? Did I miss something, or does someone know a workaround ?

Best wishes,
Matthias
 

Share this post


Link to post
Share on other sites

Hi,

The main problem with 129 series when migrating software is system clock setting, which changed a lot - new options for PLL settings at 320/480MHz - so check the system settings clock and to be sure it works correctly. But as no inside is available for measuring frequency, the best idea is to use either UART and see if working OK or a PWM generating a prescribed waveform.

Also you can check the Tiva software, code is open. The example program qs-iot uses ADC, sample sequencer 3 to measure temperature.

L

Share this post


Link to post
Share on other sites

Clock source for this failing example is 16 MHz PIOSC, which is default for ALTCLKCFG, which is default for ADC clock on TM4C1294. I already checked for those 16 MHz by generating an interrupt driven square wave with Systick timer. PLL and MOSC XTAL are off, UART0 is running on PIOSC, too.

Tivaware examples unfortunately are of limited help for me as the calls diffuse within a huge library - I already banged my head against the adc.c in driverlibs. Do you know "direct register" examples for TM4C1294 ?

Matthias

BTW, off-topic: I found out that the simple ethernet transmit descriptors are non-functional, a silicon bug circumvented in Tivaware library by always enabling the advanced descriptor format for transmit packets, but this is not documented in chip errata. For this reason I got suspicious.
 

Share this post


Link to post
Share on other sites

This is all my hardware startup code accompanying the example above. All other IO registers are on Reset default.


 

 movw r1, #0x7FFF    @ Activate clock for all GPIOs
  ldr  r0, =RCGCPIO
  str  r1, [r0]

  movs r1, #1         @ Activate clock for UART0
  ldr  r0, =RCGCUART
  str  r1, [r0]

  movs r1, #0x11      @ Set special function for PA0 and PA1
  ldr r0, =GPIO_PORTA_AHB_PCTL_R
  str r1, [r0]

  movs r1, #3         @ Set special function for PA0 and PA1
  ldr  r0, =GPIO_PORTA_AHB_AFSEL_R
  str  r1, [r0]

  @ movs r1, #3       @ Set special function for PA0 and PA1
  ldr  r0, =GPIO_PORTA_AHB_DEN_R
  str  r1, [r0]

  movs r1, #0         @ UART stop
  ldr  r0, =UARTCTL
  str  r1, [r0]

  @ Baud rate generation:
  @ 16000000 / (16 * 115200 ) = 1000000 / 115200 = 8.6805
  @ 0.6805... * 64 = 43.5   ~ 44
  @ use 8 and 44

  movs r1, #8
  ldr  r0, =UARTIBRD
  str r1, [r0]

  movs r1, #44
  ldr  r0, =UARTFBRD
  str r1, [r0]

  movs r1, #0x60|0x10  @ 8N1, enable FIFOs !
  ldr  r0, =UARTLCRH
  str r1, [r0]

  movs r1, #5          @ Choose ALTCLKCFG = PIOSC (default) as source
  ldr  r0, =UARTCC
  str r1, [r0]

  movs    r1, #0
  ldr     r0, =UARTFR
  str r1, [r0]

  movw r1, #0x301      @ UART start
  ldr  r0, =UARTCTL
  str  r1, [r0]

Share this post


Link to post
Share on other sites

Hi,

ADC clock must be configured also (new in Tiva-129!) with the call:
ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_FULL, 1);
 
And this one can be read (from driverlib/adc.c) as (neglecting first some assertions):
    //
    // Write the sample conversion rate.
    //
    HWREG(ui32Base + ADC_O_PC) = (ui32Config >> 4) & ADC_PC_SR_M;
 
    //
    // Write the clock select and divider.
    //
    HWREG(ui32Base + ADC_O_CC) = (ui32Config & ADC_CC_CS_M) |
                                 (((ui32ClockDiv - 1) << ADC_CC_CLKDIV_S)) ;
 
As you can see, all these are based on HWREG macro, defined in inc/hw_types.h as:
#define HWREG(x)             (*((volatile uint32_t *)(x)))
which I assume you know it. You may verify these and get additional code for your case.
If you pre-process the above snippet, you will have an instant conversion of all constants or you can transform them into direct register access.
L

Share this post


Link to post
Share on other sites

In section 15.4 "Initialisation and Configuration" of chip datasheet nothing is said about the need to set clock registers. But I tried nonetheless:
 

#define ADC_CLOCK_RATE_FULL     0x00000070
#define ADC_CLOCK_RATE_HALF     0x00000050
#define ADC_CLOCK_RATE_FOURTH   0x00000030
#define ADC_CLOCK_RATE_EIGHTH   0x00000010

#define ADC_CLOCK_SRC_PLL       0x00000000
#define ADC_CLOCK_SRC_PIOSC     0x00000001
#define ADC_CLOCK_SRC_ALTCLK    0x00000001
#define ADC_CLOCK_SRC_MOSC      0x00000002

#define ADC_CC_CS_M             0x0000000F  // ADC Clock Source


ADCClockConfigSet(ADC0_BASE,         ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_FULL, 1);
ADCClockConfigSet(uint32_t ui32Base, uint32_t ui32Config,                       uint32_t ui32ClockDiv)
                                     0x00000001            0x00000070                    1     
                                      
    //
    // Write the sample conversion rate.
    //
    HWREG(ui32Base + ADC_O_PC) = (ui32Config >> 4) & ADC_PC_SR_M;

    7 ADC0_PC !

    //
    // Write the clock select and divider.
    //
    HWREG(ui32Base + ADC_O_CC) = (ui32Config & ADC_CC_CS_M) |
                                 (((ui32ClockDiv - 1) << ADC_CC_CLKDIV_S)) ;

                                 1 | 0 << ... = 1.
    1 ADC0_CC !


Evaluating this gives exactly the reset-default values for CC and PC. Setting those registers to their reset value again does not change the problem:

$400FE638 constant RCGCADC

: init-analog ( -- )
  $1 RCGCADC ! \ Provide clock to AD-Converter
               \ PIOs already activated in Core
  50 0 do loop \ Wait a bit
;

$40038000 constant ADC0_ACTSS
$40038044 constant ADC0_SSCTL0
$40038028 constant ADC0_PSSI
$40038048 constant ADC0_SSFIFO0

$40038FC4 constant ADC0_PC              
$40038FC8 constant ADC0_CC              


: temperature ( -- Measurement )

  1 ADC0_CC !      \ ALTCLK = PIOSC, divide by 1
  7 ADC0_PC !      \ Full sample rate

  0 ADC0_ACTSS !   \ Disable Sample Sequencers
 $A ADC0_SSCTL0 !  \ First Sample is from Temperature Sensor and End of Sequence
  1 ADC0_ACTSS !   \ Enable Sample Sequencer 0
  1 ADC0_PSSI !    \ Initiate sampling

  begin $10000 ADC0_ACTSS bit@ not until \ Check busy Flag for ADC

  ADC0_SSFIFO0 @ \ Fetch measurement result
;

init-analog temperature .

Share this post


Link to post
Share on other sites

Hi,

Please be careful - the excerpt in blue is part of the function mentioned above - you do not need to repeat again. I was trying to suggest you to read the code in driverlib, to see it is easy to decipher and then use.

Now, I suggest again to read the comments of that function in driverlib. I recognize the user manual is/has some problems, but the main descriptions are in the followings:

-paragraph 18.3.2.6 - Module clocking

-paragraph 5.2.5.2 - page 247 ADC Clock Control

But I use what is written in driverlib - used in several other situations without problems.

L

Share this post


Link to post
Share on other sites

Main Clock tree in section 5.2.5.2 shows a direct PIOSC line to the ADC CS, just as expected.

Finally, section 15.3.2.7 gives an hint:

16 MHz PIOSC. Using the PIOSC provides a conversion rate near 1 Msps. To use the PIOSC
to clock the ADC, first power up the PLL and then enable the PIOSC in the CS bit field in the
ADCCC register, then disable the PLL.

Stange procedure, but now it finally works. Thank you for pointing me to the right section ! Next release of Mecrisp-Stellaris will finally include an ADC example.

PS: Mecrisp-Stellaris is written in bare metal assembly and not compatible with the C calling conventions, so I cannot hook the driverlib into.
 

Share this post


Link to post
Share on other sites

Hi,

I realized you use .asm - but for general knowledge driverlib understanding does not hart - neither a second toolchain usage. About driverlib (and to be fair also about CMSIS library) - you may have help when someting goes wrong, another metod to test/verify a function or a concept. Also, all these functions reside inside on-chip ROM and are ready to be called from application.

L

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...