M-atthias 50 Posted May 26, 2014 Share Posted May 26, 2014 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 Quote Link to post Share on other sites
Lyon 3 Posted May 26, 2014 Share Posted May 26, 2014 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 M-atthias 1 Quote Link to post Share on other sites
M-atthias 50 Posted May 26, 2014 Author Share Posted May 26, 2014 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 ?MatthiasBTW, 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. Quote Link to post Share on other sites
M-atthias 50 Posted May 26, 2014 Author Share Posted May 26, 2014 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] Quote Link to post Share on other sites
Lyon 3 Posted May 26, 2014 Share Posted May 26, 2014 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 M-atthias 1 Quote Link to post Share on other sites
M-atthias 50 Posted May 27, 2014 Author Share Posted May 27, 2014 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 . Quote Link to post Share on other sites
Lyon 3 Posted May 27, 2014 Share Posted May 27, 2014 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 M-atthias 1 Quote Link to post Share on other sites
M-atthias 50 Posted May 27, 2014 Author Share Posted May 27, 2014 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 PIOSCto clock the ADC, first power up the PLL and then enable the PIOSC in the CS bit field in theADCCC 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. Quote Link to post Share on other sites
Lyon 3 Posted May 27, 2014 Share Posted May 27, 2014 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 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.