RISCV_ADCLP USER GUIDE


REVISION HISTORY

Revision No.
Description
Date
1.0
  • Initial release
  • 09/06/2024
    1.1
  • Improve hardware function and FAQ description
  • 04/14/2025
    1.2
  • added description of channel mode
  • 06/13/2025

    1. OVERVIEW

    The Successive Approximation ADC uses a feedback comparison circuit structure. The implementation method is briefly summarized as follows: take a digital quantity and add it to the DAC to get a corresponding output analog voltage. Compare this analog voltage with the input analog voltage signal. If the two are not equal, adjust the digital quantity until the two analog voltages are equal. The final digital quantity is the desired conversion result.

    2. KEYWORD DESCRIPTION

    • ADCLP

      Analog-to-digital converter Low Precision, low-precision (10-bit) analog-to-digital converter.

    • ADCMP

      Analog-to-digital converter Medium Precision, medium-precision (12bit) analog-to-digital converter.

    • Upper/lower bound

      ADCLP can set the upper and lower limits of the external input voltage digital quantity, and an interrupt will be triggered if it exceeds the range.

    • Reference voltage

      The reference voltage used for analog-to-digital conversion calculations, which is also the maximum range. If the reference voltage is set to 1.8v, when the external input voltage is >=1.8v, the digital value reaches the maximum value of 1023.

    3. FUNCTION DESCRIPTION

    3.1. Hardware Function Description

    • SAR ADCLP has a total of 5 channels that can support analog-to-digital conversion of external input voltage.

    • The sampling accuracy is 10 bits, so the acquired register value range is 0~0x3ff.

    • Supports switching of two-level reference voltage (i.e. full scale), which are 1.8V and 1.0V respectively.

    • Sampling frequency = 12Mhz / 104 = 115384hz (equivalent to a sampling interval of 8667ns per point on the hardware).

    • The channel mode can be selected from 1 channel / 4 channel / 8 channel / 9 channel. Different modes determine the time interval for data update. If 1 channel mode is selected, it means that the hardware only enables 1 channel, and the time interval for ADC data update is 8667ns. If 4 channel mode is selected, the time interval for ADC data update is (8667ns * 4)

    • Supports threshold setting of external input voltage. When the voltage exceeds the threshold range, an interrupt will be triggered. The response time of the hardware interrupt (excluding software processing time) will be affected by the time interval of ADC data update. If the 1-channel mode is selected, the response time of the hardware interrupt is at least greater than 8667ns. If the 4-channel mode is selected, the response time of the hardware interrupt is at least greater than (8667ns * 4)

    3.2. Calculation instructions

    The main function of SAR ADCLP is to convert analog signals into corresponding digital signals, that is, it can convert the input voltage into digital quantities and store them in registers, and calculate the input voltage through the formula.

    Calculation formula: voltage = (register value / full scale) * reference voltage.

    That is, if the value read is 0x1D2, the voltage is 0x1D2/0x3FF *1.8 = about 0.82v.

    4. HARDWARE CONNECTION INTRODUCTION

    As shown in the figure below, the external voltage can be connected to the pins PM_SAR_GPIO0~PM_SAR_GPIO4.

    5. RTOS USAGE INTRODUCTION

    5.1. DRIVER PATH

    sc/driver/sysdriver/saradc/os/adclp_os.h
    sc/driver/sysdriver/saradc/drv/pub/drv_adclp.h
    sc/driver/sysdriver/saradc/drv/src/drv_adclp.c
    sc/driver/sysdriver/saradc/drv/src/drv_adclp_test.c
    sc/driver/sysdriver/saradc/hal/chipname/src/hal_adclp.c
    sc/driver/sysdriver/saradc/hal/chipname/inc/hal_adclp.h
    sc/driver/sysdriver/saradc/hal/chipname/inc/hal_adclp_cfg.h
    

    5.2. CONFIG Configuration

    The config file is located at mak/options_chipname_riscv_isw.mak, enable CONFIG_SARADC_SUPPORT

    # Feature_Name = [DRV] SARADC driver support
    # Description = SARADC driver support
    #Option_Selection = TRUE, FALSE
    CONFIG_SARADC_SUPPORT = TRUE
    

    5.3. SYSDESC Configuration

    The chipname_xxx.sys file is located in sc/driver/sysdriver/sysdesc/hal/chipname/pub

    <adclp0>
        [reg_u32] 0x2002800;
        [interrupts_u32] INT_PM_IRQ_SAR_KP;
        [camclk_u16] CAMCLK_sar;
        [interrupts_en_u8] 1;
        [ref_vol_u32] 1800;
        [upper_bound_u16] 0x3FF;
        [lower_bound_u16] 0;
        [status_u8] 0;
    
    Property Description Value Note
    reg_u32 Set adclp bank address 0x2002800 Modification prohibited
    interrupts_u32 Set hardware interrupt number INT_PM_IRQ_SAR_KP Modification prohibited
    camclk_u16 Set clock source CAMCLK_sar Modification prohibited
    interrupts_en_u8 Enable interrupts 1: enable, 2: disable Can be modified as needed
    ref_vol_u32 Set the reference voltage level In mv, supports 1800mv and 1000mv Can be modified as needed
    upper_bound_u16 Set the upper threshold voltage 0~0x3FF, enable interrupt Can be modified as needed
    lower_bound_u16 Set the lower threshold voltage 0~0x3FF, enable interrupt Can be modified as needed
    status_u8 Whether adclp enables the driver 1: enable, 2: disable Can be modified as needed

    The number of channels enabled by adclp determines the channel mode of the hardware:

    • When only one channel is enabled, the hardware uses 1 channel mode

    • When multiple channels are enabled, the maximum value of the X in node name "adclpX" is < 4, and the hardware uses 4 channel mode

    • When multiple channels are enabled, the maximum value of the X in node name "adclpX" is >= 4, and the hardware uses 8 channel mode

    5.4. PADMUX settings

    SAR-ADCLP does not require padmux configuration, and the PIN pin is configured as ADC sampling function by default

    5.5. Sample Cpde

    The demo source code is located in sc/driver/sysdriver/saradc/drv/src/drv_adclp_test.c

    #define ADC_CHANNEL_NUM 8
    static adclp_cb_t cb_t[ADC_CHANNEL_NUM]       = {0};
    static u8         adclp_init[ADC_CHANNEL_NUM] = {0};
    
    /* Callback function, this function will be called when the voltage exceeds the threshold range*/
    
    {
        u16 data;
    
        drv_adclp_get_data(channel, &data);
        cliPrintf("adclp%hhu data[%hu] exceeding bound\n", channel, data);
    
        return 0;
    }
    
    static int adclp_test(CLI_t *cli, char *p)
    {
        u8    i;
        int   ret;
        char *cmd;
        u16   data;
        u8    argc;
        u32   channel;
    
        argc = CliTokenCount(cli);
        if (argc < 1)
            goto adclp_help_exit;
    
        cmd = CliTokenPop(cli);
        if (strcmp(cmd, "init") == 0)
        {
            argc = CliTokenCount(cli);
            if (argc != 1)
                goto adclp_help_exit;
    
            if (CliTokenPopNum(cli, &channel, 0) != eCLI_PARSE_OK)
                goto adclp_help_exit;
    
            if (channel >= ADC_CHANNEL_NUM)
            {
                cliPrintf("channel[%hhu] not supported\n", (u8)channel);
                goto adclp_help_exit;
            }
    
            if (adclp_init[channel])
            {
                cliPrintf("channel[%hhu] already init\n", (u8)channel);
                return eCLI_PARSE_OK;
            }
    
            //Register callback function
            cb_t[channel] = adclp_get_data;
            ret           = drv_adclp_register_callback(channel, cb_t[channel]);
            if (ret)
                return -eCLI_PARSE_INVALID_PARAMETER;
    
            //Set the threshold
            ret = drv_adclp_set_bound((u8)channel, 600, 400);
            if (ret)
                return -eCLI_PARSE_INVALID_PARAMETER;
    
            adclp_init[channel] = 1;
        }
        else if (strcmp(cmd, "single") == 0)
        {
            argc = CliTokenCount(cli);
            if (argc != 1)
                goto adclp_help_exit;
    
            if (CliTokenPopNum(cli, &channel, 0) != eCLI_PARSE_OK)
                goto adclp_help_exit;
    
            if (!adclp_init[channel])
            {
                cliPrintf("channel[%hhu] must init first\n", (u8)channel);
                return eCLI_PARSE_OK;
            }
    
            //Get the voltage digital value of a single channel
            ret = drv_adclp_get_data((u8)channel, &data);
            if (ret)
                return -eCLI_PARSE_INVALID_PARAMETER;
            cliPrintf("channel[%hhu] data is[%hu]\n", (u8)channel, data);
        }
        else if (strcmp(cmd, "scan") == 0)
        {
            for (i = 0; i < ADC_CHANNEL_NUM; i++)
            {
                channel = i;
                ret     = drv_adclp_get_data((u8)channel, &data);
                if (ret)
                    return -eCLI_PARSE_INVALID_PARAMETER;
                cliPrintf("channel[%hhu] data is[%hu]\n", (u8)channel, data);
            }
        }
        else
        {
        adclp_help_exit:
            cliPrintf("command format : adclp init   [channel]\n");
            cliPrintf("command format : adclp single [channel]\n");
            cliPrintf("command format : adclp scan\n");
            return -eCLI_PARSE_INVALID_PARAMETER;
        }
    
        return eCLI_PARSE_OK;
    }
    

    6. API Reference

    API can refer to the header filesc/driver/sysdriver/saradc/drv/pub/drv_adclp.h

    enum adclp_vdd_type
    {
        ADCLP_VDD_CPU = 0,
        ADCLP_VDD_DLA,
        ADCLP_VDD_MIU,
        ADCLP_VDD_CORE,
        ADCLP_VDD_NODIE,
        ADCLP_VSS,
    };
    
    typedef int (*adclp_cb_t)(u8 channel);
    
    int drv_adclp_enable(u8 channel, u8 enable);
    int drv_adclp_get_data(u8 channel, u16 *data);
    int drv_adclp_set_bound(u8 channel, u16 upper_bound, u16 lower_bound);
    int drv_adclp_vdd_data(u8 channel, u16 *data, enum adclp_vdd_type type);
    int drv_adclp_register_callback(u8 channel, adclp_cb_t cb_t);
    int drv_adclp_unregister_callback(u8 channel, adclp_cb_t cb_t);
    

    6.1. drv_adclp_set_bound

    • Purpose

      Set the threshold of the specified channel

    • Syntax

      int drv_adclp_set_bound(u8 channel, u16 upper_bound, u16 lower_bound)
      
    • Parameter

      Parameter Name Description
      channel Sampling channel
      upper_bound Upper threshold value
      lower_bound Lower threshold value
    • Return value

      Return value Description
      0 Setting successful
      -4 Channel not supported

    6.2. drv_adclp_get_data

    • Purpose

      Get the external input voltage digital value of the specified channel

    • Syntax

      int drv_adclp_get_data(u8 channel, u16 *data)
      
    • Parameter

      Parameter Name Description
      channel sampling channel
      data voltage digital quantity
    • Return value

      Return value Description
      0 Sampling successful
      -4 Channel not supported

    6.3. drv_adclp_register_callback

    • Purpose

      Register the callback function of the specified channel (the same channel supports registering multiple callback functions). When the sampling result exceeds the threshold, the corresponding processing can be done in the callback function.

    • Syntax

      int drv_adclp_register_callback(u8 channel, adclp_cb_t cb_t)
      
    • Parameter

      Parameter Name Description
      channel Sampling channel
      cb_t Function pointer
    • Return value

      Return value Description
      0 Registration successful
      -6 Registration failed

    6.4. drv_adclp_unregister_callback

    • Purpose

      Release the callback function of the specified channel and the memory applied during registration

    • Syntax

      int drv_adclp_unregister_callback(u8 channel, adclp_cb_t cb_t)
      
    • Parameter

      Parameter Name Description
      channel Sampling channel
      cb_t Function pointer
    • Return value

      Return value Description
      0 Unregistration successful
      -6 Unregistration failed

    6.5. drv_adclp_enable

    • Purpose

      Enable the sampling function of the specified channel

    • Syntax

      int drv_adclp_enable(u8 channel, u8 enable);
      
    • Parameter

      Parameter Name Description
      channel Sampling channel
      enable Enable or not
    • Return value

      Return value Description
      0 Success
      -4 Channel not supported

    6.6. drv_adclp_vdd_data

    • Purpose

      Get the adc code of a special channel without external input voltage. The adc code value depends on the type passed in by adclp_vdd_type.

    • Syntax

      int drv_adclp_vdd_data(u8 channel, u16 *data, enum adclp_vdd_type type)
      
    • Parameter

      Parameter Name Description
      channel Here it is specified as 8
      data Voltage digital quantity
      type Enumeration,choose VDD_CORE,VDD_CPU,VDD_DLA, etc
    • Return value

      Return value Description
      0 Success
      -4 Channel not supported

    7. FAQ

    Q1:ADCLP Device Does Not Exist

    1. Check if the status of the sysdesc adclp node is 1

    2. Check if the config is configured, see [5.2. Config Configuration]

    Q2: The external input voltage changes, but the SAR ADCLP sampling data does not change

    1. When the PIN is in GPIO MODE, the sampling data will not change. You can read the register value to determine whether the PIN is switched to GPIO MODE:

      0x14 0x11 BIT0-BIT5:
      Each BIT of BIT0~BIT5 corresponds to a channel. When value=0, the PIN pin of the channel is in GPIO MODE. When value=1, the PIN pin of the channel is in ADC MODE. For example, when BIT0=0, channel 0 is in GPIO MODE. When BIT1=1, channel 1 is in ADC MODE.
      
      0x14 0x11 BIT8-BIT13:
      Each BIT of BIT8~BIT13 corresponds to a channel. The prerequisite is that the PIN pin is in GPIO MODE. When value=0, the PIN pin is switched to output. When value=1, the PIN pin is switched to input.
      
      0x14 0x12 BIT0-BIT5:
      Each BIT of BIT0~BIT5 corresponds to a channel. The prerequisite is that the PIN pin is in GPIO MODE and is set to ouput. When value=0, the PIN pin of the channel is switched to a low level. When value=1, the PIN pin of the channel is switched to a high level.
      
      For example: riu_r 0x14 0x11
      Return value: 0x3F3F -> All channels are in ADC MODE
      Return value: 0x3E3E -> Channel 0 is in GPIO MODE, and the rest of the channels are in ADC MODE
      Return value: 0x0000 -> All channels are in GPIO MODE and switched to output
      
    2. When the PIN pin register is set to non-GPIO MODE, the sampled data still does not change. You can set the PIN pin to GPIO MODE and perform an output high/low test. If the PIN pin level cannot be pulled up or down, it can be judged as a hardware problem.

    Q3: The first or first few sampling data have a large deviation from the actual input voltage

    This problem is most likely related to the sampling timing. You can use GPIO as a trigger source to obtain the voltage status of the component at each sampling.

    As shown in the figure below, before triggering ADC sampling, GPIO switches from high level to low level. The ADC sampling timing is just in the process of voltage decline, not when the voltage is stable. Therefore, it is judged as sampling abnormality. At this time, it is necessary to wait until the component is stable before sampling.