This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RM48L952: Need help for TI Chip Hercules RM48L952ZWT generating 48 kHz clock on N2HET1[8] per TI example Datasheet

Part Number: RM48L952
Other Parts Discussed in Thread: HALCOGEN,

I am attempting to follow TI data sheet (spna227.pdf) to trigger ADC1 with N2HET timer.

I need NHET to generate 48 kHz trigger signal.

Triggering ADC Using Internal Timer Events on Hercules MCUs

I understand this data sheet.  I followed the example and created N2HET micromachine program using the HET Assembler.

The problem is, I don't know how to setup the following parameters to make the loop count correctly so the N2HET makes a periodic 48 kHz trigger signal.

Here's my program, taken from TI Document (spna227.pdf)

L00 CNT  {REG=A, max=8, data=0}
L01 ECMP {next=L00, hr_lr=HIGH, en_pin_action=ON, pin=8, action=PULSELO, reg=A, data=4, hr_data=0}

It looks like I might need to adjust some or all of the following parameters in one (or both) the HALCoGen and N2HET IDE, but I'm not sure how all the math works:

  • In the HALCoGen
    • in tab RM48L952 --> GCM
      • VCLK2 Divider (to make VCLK2)
    • in HET1 --> HET1 Global Timing Configuration
      • HR Prescale
      • LR Prescale
      • (I tried to set these, but it looks like I need to set these in the HET IDE Assembler tool)
  • In the HET IDE Assembler tool
    • "max=8"   (from program, L00, above)
    • "data=4" (from program, L01, above)

Also, another big problem is when I change VCLK2 in the HALCoGen from the 100 MHZ default rate, the Hercules Development Kit we are using default 'C' code doesn't boot and hangs at the RAM initialization for the PCB.  This seems strange to me but maybe changing the clock rate causes a timing problem with the default self test for HET peripheral?  I'm not sure about this.

So far I spent about 3 days trying to figure this out, but I don't seem to understand the maths involved in the HET program and the HET clock divider circuits.

The good news is my test setup is working and I do see an 86.xxx kHZ periodic square wave on the output of N2HET1[8], so I know the loop is running, I just have wrong frequency.

  • New Information.  I found the PWM generator in the HET IDE, and used it to generate the following code:

    ;PWM code for given HCLK frequency = 100MHz  ,PWM frequency = 0.048MHz  ,duty cycle = 0.5% ,HETPFR value =0 is below:

    L00 CNT {reg=A, max=2082, data=0}
    L01 ECMP {next=L00,hr_lr=HIGH,en_pin_action=ON,pin=8,action=PULSELO,reg=A,data=1041,hr_data=0}

    I put my oscilloscope on the output pin N2HET1[8], but the waveform measures 375 Hz, not 48 kHz. 

    However if you do the maths 48,000/375 == 128, so the frequency is off by a factor of 128. 

    So I look at the HET1 scaling register and find that the HALCoGen is default populating HETPFR[10:8] with binary '111', which corresponds to a 128 scale factor.  So, after loading the code, and booting, I overwrite the '111' in this register with'0', but get:

    --> NO OUTPUT CLOCK WAVEFORM AT ALL

    --> So, I do some testing. 

    After the HALCoGen integrates the code from the HET IDE *.h and *.c files for the program, I compile and load the code int the Hercules DEV Kit, run the code through the hetInit() which copies the program to HET RAM, I then

    --> modify the output HALCoGen startup code in het.c, and discover that when I change the value in HETPFR[10:8], as per below the following happens when I run the code(see table):

    HETPFR[10:8] in binary Frequency (Hz)
    111 375
    110 750
    101 1500
    100 3000
    011 6000
    010 12000
    001 (no clock output on pin 8)
    000 (no clock output on pin 8)

    So, just when I think I am going to succeed by putting '000' (binary) value into HETPFR[10:8], the timer outputs NO CLOCK AT ALL on pin 8.

    I think there is some basic, simple thing I am doing that is not correct, but I don't know what it is.  Since the output frequency is doubling per the the way the clock divider works, I think when I go from '010' binary to '000' binary that the output frequency will be 12,000 Hz * 2 *2 = 48,000 Hz (what I want), but instead I get no signal at all, just 0 Volts, logic 'Low'.

    Please help if you know the answer to this.  Thank-you. 

  • Hi Kip,

    I started working on your issue and will provide you an update ASAP.

    --
    Thanks & regards,
    Jagadish.

  • Any progress on this yet?

  • Any progress on this yet?

  • Hi Kip,

    My sincere apologies for the delay in my response. Actually, i am on leave for few days in last week, and also so many issues i had gone through this mean time.

    Regarding this issue, i create one example project for you to generate the 48Khz signal using N2HET on HET1_27 pin.

    Here is the output:

    This is how i generated this signal.

    1. First i configured Loop Resolution value as minimum as possible, 

    I configured this loop resolution as 145nS. If this loop resolution high, then we will get more error in the waveform. For more details refer below thread:

    (+) TMS570LS3137: PWM Capturing Code is working incorrectly - Arm-based microcontrollers forum - Arm-based microcontrollers - TI E2E support forums

    2. Based on this loop resolution value and required frequency, now i calculated the max value in the CNT instruction.

    Required Frequency = 48Khz

    Required Period = 20.83uS

    Loop Resolution = 145.45nS or 0.14545uS

    so, max value =Required period / Loop Resolution = 20.83 / 0.14545 = 143 (aprox)

    So, i configured final max value as 142.

    As i need 50% duty cycle, so i configured half of 142 that is 71 in the data value of ECMP instruction.

    3. After doing above things i generated the .h and .c from HET IDE and i configured same files in the HALCoGen. In addition i make sure the direction as output for the pin i am generating pulse.

    4. Now after generating HALCoGen code and program into the board i got 48Khz signal as shown in my first image.

    I am attaching my main project and HET project for your reference:

    48KHZ_Signal_using_HET_IDE_RM46.zip

    RM46_48KHZ_TEST_HET.zip

    Note:
    As i don't have RM48 board i did these tests on my RM46 board but mostly same modifications will be applicable for RM48 as well.

    --
    Thanks & Regards,
    Jagadish.

  • I have a new problem with 48kHz clock. (This HET works very strange.  I am trying to understand)

    My goal is I connect output of HET1 to HET1[8] and use this as input trigger to sample ADC1 channels { 0,1,2,3,4,5,6,7 } == ADC1 { 0..7 }

    I am sending sinusoid signal to input on all ADC1 channels { 0 . . . 7 }

    • OK, Now I am complete my HET Program, counter program,  compile and build in to image with HALCOGEN
    • In Halcogen, I setup to sample first 8 channels, continuous, with 16 channel BUF boundary, so ADC1 will force interrupt for every 8 ADC1 samples.
    • I am using 16 word buffer in ADC1.
    • When processor boots, I have some code where I overwrite some HET configuration registers because I cannot edit values in config registers in HAL.  (In help you give above, you say edit this box, but I CANNOT edit it in RM48L952ZWT gui, this box cannot be changed. )  So I .  I do some experiments and using PINMUX can read HET1[8] output signal with oscilloscope and it is almost perfect frequency :  47.97 kHz. So, I succeed in generating 48 kHz signal external to chip, but ADC1 sample rates are NOT 48 KHz.   Let me explain .  ( Note, my processor is RM48L952ZWT (BGA) and you are using RM46 class, is different maybe? )
    • I have code to service Interrupt Service Routine from ADC1, where I measure 48 kHz rate, so I am trying to sample each signal at 6 kHz, so I use 48 kHz base clock and Divide by 8 = 6 kHz rate for each channel -- because each is 60 Hz waveform and I want 100 samples.  I have code to de-interleave. 
    • When I use TI Code Composer Studio (CCS) and JTAG debugger, I look at my 100 word transfer buffer from ADC, where I move 8 samples from buffer x 100 interrupts to get 100 samples in each buffer.
    • Then I use CCS "graph" button.  I get very good sinusoid waveform, but WRONG frequency sample rate.  I estimate that sample rate is 2.63 times too fast, or about 48 * 2.83 for about 126.3 kHz.  I look at raw data to get this estimate, not output of TI "graph" function.

    So, big question here -- I see 48 kHz sample rate on HET1[8] output pin, but ADC converter seem like converting 2.83 times TOO fast.  Can you help to explain? 

  • Hi Kip, 

    My sincere apologies for the delay in my response.

    Actually, we got some holidays in TI-India. And also, i was stuck with so many other issues in this mean time.

    In Halcogen, I setup to sample first 8 channels, continuous, with 16 channel BUF boundary, so ADC1 will force interrupt for every 8 ADC1 samples.

    I think we should not enable "continuous conversion" for this case. If we do enable it then it will only take the first trigger of HET signal and then it continuously starts conversion.

    Actually, our requirement is that we should need to convert the ADC with the 48KHz frequency, that means we need to convert with the period of 20.83us between the conversions.

    --
    Thanks & Regards,
    Jagadish.

  • I solved the problem.  When using external trigger, I found it necessary to write the ADC registers manually.

    Here's the code:

    << startup code >>

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #define INCLUDE_ADC_CODE
    #ifdef  INCLUDE_ADC_CODE
        adcInit();
        adcInit_XDER(); // (no system stuff here)

        adcEnableNotification   (adcREG1, adcGROUP0);

        // don't need to start conversion since it is externally triggered
        //    adcStartConversion      (adcREG1, adcGROUP0);

        /** - Start Conversion */
        adcREG1->GxSEL[0] = 0xFF;  // channels 0-7, inclusive

        // Note:  Fn. adcInit(), assignment of a value to hetREG1->GCR results in flags '0b1001' (binary) getting set in adcREG1->GxINTFLG[0U].
        //        Clear the flags here so as not to trigger an interrupt before the HET is configured
        adcREG1->GxINTFLG[0U] = 9U;  /**< 0x0034,0x0038,0x003C: Group 0-2 interrupt flag register   */

        // select HET[8] as trigger
        adcREG1->EVSRC = (uint32)0x00000001U; /**< 0x001C: Group 0 trigger source control register           */
    #endif

    #define INCLUDE_HET_CODE
    #ifdef  INCLUDE_HET_CODE
        //++++++++++++++++++++++++++++++++++++++
        hetInit();
        hetInit_XDER(); // used to adjust timing problem in developing 48kHz clock
    #endif


    << Code inside ISR >>

    bool ADC1_ISR_First_Time_Completed = false;

    void adc1Group0Interrupt_Handler_XDER_C_Wrapper()
    {
        if (ADC1_ISR_First_Time_Completed == false) // skip the first wrong samples  TODO XDER fix this later
        {
            ADC1_ISR_First_Time_Completed = true;
            goto Exit_ADC_Handler;
        }

        for (uint16 i = 0; i < (SAMPLES_PER_INTERRUPT / 8); i++) // integer math must be MOD 8
        {
            for (int j = 0; j < 8; j++)
            {
                // move 12-bit sample from ADC FIFO to RAM buffer, remove the channel ID in the upper 4 bits
                uint32 addr = ADC_1_Base_Address + ((8 * 4) * i) + (j * 4);

                // Mask off the top 4 bits, which hold the sample number ID
                I_Line_Load_1_2[j][ADC_1_Index_Sample_Number] = *(uint32*)addr & 0xfff;
            }
            ADC_1_Index_Sample_Number++;
        }

        if (ADC_1_Index_Sample_Number == 1)
        {
            Breakpoint_1++;
        }
        else if (ADC_1_Index_Sample_Number == 2)
        {
            Breakpoint_1++;
        }
        else if (ADC_1_Index_Sample_Number == 100)
        {
            Breakpoint_1++;
            ADC_1_Index_Sample_Number = 0; // buffer wrap
        }

    Exit_ADC_Handler:

        // reset the interrupt flag.  !! If you don't do this, the ISR will spin recursively
        adcREG1->GxINTFLG[0] = 9U;

        /** - Start Conversion */
        adcREG1->GxSEL[0] = 0xFF;  // channels 0-7, inclusive

    }