Hello sir, I have some question regarding your code please. What is the maximum sampling rate that I can get using this code and what should I change to get that sampling rate? If I want to read from all 7 analog pins, how can I do that?
Thank you for your help and your effort. On Tuesday, April 8, 2014 1:15:31 PM UTC+3, Youngtae Jo wrote: > > I've tried to find some example of ADC reading by PRU for my project, but > I couldn't find it. > And I made that of source code and attach here for some people who have > the same problem with me. > I hope it will be helpful. > > [ AM335x ARM-CORE PRU ADC Example ] > - Sequence of example > 1. Install compiling environment of PRU > 2. Enable PRU > 3. Enable ADC > 4. Example source > - This example source collects ADC data from AIN0 pin with 16khz > sampling rate. > - The collected data are saved into "Results.txt" file. > - The example source are "Makefile", "ADCCollector.c", "ADCCollector.p", > "ADCCollector.hp" > > [ Install compile environment ] > 1. Get a copy of the am335x_pru_package -> > https://github.com/beagleboard/am335x_pru_package > You also can download the am335x_pru_package here -> > https://github.com/beagleboard/am335x_pru_package/archive/master.zip > 2. If you downloaded the archive, unpack it somewhere under your home > directory. > 3. Make a new directory /usr/include/pruss/ and copy the files prussdrv.h > > and pruss_intc_mapping.h into it (from > am335x_pru_package-master/pru_sw/app_loader/include). > Check the permissions; if you used the .zip file, these headers will > likely have the execute bits on. > It doesn't really hurt anything, but is certainly not what you want. > 4. Change directory to > am335x_pru_package-master/pru_sw/app_loader/interface > then run: CROSS_COMPILE= make (note the space between the = and the > command). > 5. The previous step should have created four files in > am335x_pru_package-master/pru_sw/app_loader/lib: libprussdrv.a, > libprussdrvd.a, libprussdrvd.so and libprussdrv.so. > Copy these all to /usr/lib then run ldconfig. > 6. Change directory to am335x_pru_package-master/pru_sw/utils/pasm_source > then run source linuxbuild to create a pasm executable one directory > level up. > - If linuxbuild doesn't have permission to execution, give the permission > by run this > : chmod +x linuxbuild > Copy it to /usr/bin and make sure you can run it. > If you invoke it with no arguments, you should get a usage statement. > > [ Enable PRU ] > Before using PRU, we need to enable the PRU core, you can do it as shown > below > # echo BB-BONE-PRU-01 > /sys/devices/bone_capemgr.8/slots > > [ Enable ADC ] > Before using ADC, we also need to enable ADC, you can do it as shown below > # echo cape-bone-iio > /sys/devices/bone_capemgr.*/slots > > [ ADC Example - Makefile] > CFLAGS+=-Wall -Werror > LDLIBS+= -lpthread -lprussdrv > > all: ADCCollector.bin ADCCollector > > clean: > rm -f ADCCollector *.o *.bin > > ADCCollector.bin: ADCCollector.p > pasm -b $^ > > ADCCollector: ADCCollector.o > > [ ADC Example - ADCCollector.p] > // Developed by Youngtae Jo in Kangwon National University (April-2014) > > // This program collects ADC from AIN0 with certain sampling rate. > // The collected data are stored into PRU shared memory(buffer) first. > // The host program(ADCCollector.c) will read the stored ADC data > // This program uses double buffering technique. > // The host program can recognize the buffer status by buffer status > variable > // 0 means empty, 1 means first buffer is ready, 2 means second buffer is > ready. > // When each buffer is ready, host program read ADC data from the buffer. > > > .origin 0 // offset of the start of the code in PRU memory > .entrypoint START // program entry point, used by debugger only > > #include "ADCCollector.hp" > > #define BUFF_SIZE 0x00000FA0 //Total buff size: 4kbyte(Each buffer has > 2kbyte: 500 piece of data) > #define HALF_SIZE BUFF_SIZE / 2 > > #define SAMPLING_RATE 16000 //Sampling rate(16khz) > #define DELAY_MICRO_SECONDS (1000000 / SAMPLING_RATE) //Delay by sampling > rate > #define CLOCK 200000000 // PRU is always clocked at 200MHz > #define CLOCKS_PER_LOOP 2 // loop contains two instructions, one clock each > #define DELAYCOUNT DELAY_MICRO_SECONDS * CLOCK / CLOCKS_PER_LOOP / 1000 / > 1000 * 3 > > .macro DELAY > MOV r10, DELAYCOUNT > DELAY: > SUB r10, r10, 1 > QBNE DELAY, r10, 0 > .endm > > .macro READADC > //Initialize buffer status (0: empty, 1: first buffer is ready, 2: > second buffer is ready) > MOV r2, 0 > SBCO r2, CONST_PRUSHAREDRAM, 0, 4 > > INITV: > MOV r5, 0 //Shared RAM address of ADC Saving position > MOV r6, BUFF_SIZE //Counting variable > > READ: > //Read ADC from FIFO0DATA > MOV r2, 0x44E0D100 > LBBO r3, r2, 0, 4 > //Add address counting > ADD r5, r5, 4 > //Write ADC to PRU Shared RAM > SBCO r3, CONST_PRUSHAREDRAM, r5, 4 > > DELAY > > SUB r6, r6, 4 > MOV r2, HALF_SIZE > QBEQ CHBUFFSTATUS1, r6, r2 //If first buffer is ready > QBEQ CHBUFFSTATUS2, r6, 0 //If second buffer is ready > QBA READ > > //Change buffer status to 1 > CHBUFFSTATUS1: > MOV r2, 1 > SBCO r2, CONST_PRUSHAREDRAM, 0, 4 > QBA READ > > //Change buffer status to 2 > CHBUFFSTATUS2: > MOV r2, 2 > SBCO r2, CONST_PRUSHAREDRAM, 0, 4 > QBA INITV > > //Send event to host program > MOV r31.b0, PRU0_ARM_INTERRUPT+16 > HALT > .endm > > // Starting point > START: > // Enable OCP master port > LBCO r0, CONST_PRUCFG, 4, 4 > CLR r0, r0, 4 > SBCO r0, CONST_PRUCFG, 4, 4 > > //C28 will point to 0x00012000 (PRU shared RAM) > MOV r0, 0x00000120 > MOV r1, CTPPR_0 > ST32 r0, r1 > > //Init ADC CTRL register > MOV r2, 0x44E0D040 > MOV r3, 0x00000005 > SBBO r3, r2, 0, 4 > > //Enable ADC STEPCONFIG 1 > MOV r2, 0x44E0D054 > MOV r3, 0x00000002 > SBBO r3, r2, 0, 4 > > //Init ADC STEPCONFIG 1 > MOV r2, 0x44E0D064 > MOV r3, 0x00000001 //continuous mode > SBBO r3, r2, 0, 4 > > //Read ADC and FIFOCOUNT > READADC > > > > > [ ADC Example - ADCCollector.c] > > > /****************************************************************************** > * Include Files > * > > ******************************************************************************/ > // Standard header files > #include <stdio.h> > #include <stdlib.h> > #include <sys/mman.h> > #include <fcntl.h> > #include <errno.h> > #include <unistd.h> > #include <string.h> > #include <time.h> > > // Driver header file > #include <pruss/prussdrv.h> > #include <pruss/pruss_intc_mapping.h> > > > /****************************************************************************** > * Local Macro Declarations > * > > ******************************************************************************/ > #define PRU_NUM 0 > #define OFFSET_SHAREDRAM 2048 //equivalent with 0x00002000 > > #define PRUSS0_SHARED_DATARAM 4 > #define SAMPLING_RATE 16000 //16khz > #define BUFF_LENGTH SAMPLING_RATE > #define PRU_SHARED_BUFF_SIZE 500 > #define CNT_ONE_SEC SAMPLING_RATE / PRU_SHARED_BUFF_SIZE > > > /****************************************************************************** > * Functions declarations > * > > ******************************************************************************/ > static void Enable_ADC(); > static void Enable_PRU(); > static unsigned int ProcessingADC1(unsigned int value); > > > /****************************************************************************** > * Global variable Declarations > * > > ******************************************************************************/ > static void *sharedMem; > static unsigned int *sharedMem_int; > > > /****************************************************************************** > * Main > * > > ******************************************************************************/ > int main (int argc, char* argv[]) > { > FILE *fp_out; > unsigned int ret; > tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA; > int i = 0, cnt = 0, total_cnt = 0; > int target_buff = 1; > int sampling_period = 0; > > if(argc != 2){ > printf("\tERROR: Sampling period is required by second\n"); > printf("\t %s [sampling period]\n", argv[0]); > return 0; > } > sampling_period = atoi(argv[1]); > > /* Enable PRU */ > Enable_PRU(); > /* Enable ADC */ > Enable_ADC(); > /* Initializing PRU */ > prussdrv_init(); > ret = prussdrv_open(PRU_EVTOUT_0); > if (ret){ > printf("\tERROR: prussdrv_open open failed\n"); > return (ret); > } > prussdrv_pruintc_init(&pruss_intc_initdata); > printf("\tINFO: Initializing.\r\n"); > prussdrv_map_prumem(PRUSS0_SHARED_DATARAM, &sharedMem); > sharedMem_int = (unsigned int*) sharedMem; > /* Open save file */ > fp_out = fopen("Results.txt", "w"); > if(fp_out == NULL){ > printf("\tERROR: file open failed\n"); > return 0; > } > > /* Executing PRU. */ > printf("\tINFO: Sampling is started for %d seconds\n", sampling_period); > printf("\tINFO: Collecting"); > prussdrv_exec_program (PRU_NUM, "./ADCCollector.bin"); > /* Read ADC */ > while(1){ > while(1){ > if(sharedMem_int[OFFSET_SHAREDRAM] == 1 && target_buff == 1){ // First > buffer is ready > for(i=0; i<PRU_SHARED_BUFF_SIZE; i++){ > fprintf(fp_out, "%d\n", ProcessingADC1(sharedMem_int[OFFSET_SHAREDRAM + 1 > + i])); > } > target_buff = 2; > break; > }else if(sharedMem_int[OFFSET_SHAREDRAM] == 2 && target_buff == 2){ // > Second buffer is ready > for(i=0; i<PRU_SHARED_BUFF_SIZE; i++){ > fprintf(fp_out, "%d\n", ProcessingADC1(sharedMem_int[OFFSET_SHAREDRAM + > PRU_SHARED_BUFF_SIZE + 1 + i])); > } > target_buff = 1; > break; > } > } > > if(++cnt == CNT_ONE_SEC){ > printf("."); > total_cnt += cnt; > cnt = 0; > } > > if(total_cnt == CNT_ONE_SEC * sampling_period){ > printf("\n\tINFO: Sampling completed ...\n"); > break; > } > } > > fclose(fp_out); > printf("\tINFO: PRU completed transfer.\r\n"); > prussdrv_pru_clear_event (PRU_EVTOUT_0, PRU0_ARM_INTERRUPT); > > /* Disable PRU*/ > prussdrv_pru_disable(PRU_NUM); > prussdrv_exit(); > > return(0); > } > > > /***************************************************************************** > * Local Function Definitions > * > > *****************************************************************************/ > /* Enable ADC */ > static int Enable_ADC() > { > FILE *ain; > > ain = fopen("/sys/devices/bone_capemgr.8/slots", "w"); > if(!ain){ > printf("\tERROR: /sys/devices/bone_capemgr.8/slots open failed\n"); > return -1; > } > fseek(ain, 0, SEEK_SET); > fprintf(ain, "cape-bone-iio"); > fflush(ain); > return 0; > } > > /* Enable PRU */ > static int Enable_PRU() > { > FILE *ain; > > ain = fopen("/sys/devices/bone_capemgr.8/slots", "w"); > if(!ain){ > printf("\tERROR: /sys/devices/bone_capemgr.8/slots open failed\n"); > return -1; > } > fseek(ain, 0, SEEK_SET); > fprintf(ain, "BB-BONE-PRU-01"); > fflush(ain); > return 0; > } > > /* > * FIFO0DATA register includes both ADC and channelID > * so we need to remove the channelID > */ > static unsigned int ProcessingADC1(unsigned int value) > { > unsigned int result = 0; > > result = value << 20; > result = result >> 20; > > return result; > } > > > > [ ADC Example - ADCCollector.hp] > // > *****************************************************************************/ > // file: PRU_memAccess_DDR_PRUsharedRAM.hp > // > // brief: PRU_memAccess_DDR_PRUsharedRAM assembly constants. > // > // > // (C) Copyright 2012, Texas Instruments, Inc > // > // author M. Watkins > // > *****************************************************************************/ > > > #ifndef _PRU_memAccess_DDR_PRUsharedRAM_HP_ > #define _PRU_memAccess_DDR_PRUsharedRAM_HP_ > > > // *************************************** > // * Global Macro definitions * > // *************************************** > > // Refer to this mapping in the file - > \prussdrv\include\pruss_intc_mapping.h > #define PRU0_PRU1_INTERRUPT 17 > #define PRU1_PRU0_INTERRUPT 18 > #define PRU0_ARM_INTERRUPT 19 > #define PRU1_ARM_INTERRUPT 20 > #define ARM_PRU0_INTERRUPT 21 > #define ARM_PRU1_INTERRUPT 22 > > #define CONST_PRUCFG C4 > #define CONST_PRUDRAM C24 > #define CONST_PRUSHAREDRAM C28 > #define CONST_DDR C31 > > // Address for the Constant table Block Index Register (CTBIR) > #define CTBIR 0x22020 > > // Address for the Constant table Programmable Pointer Register 0(CTPPR_0) > #define CTPPR_0 0x22028 > > // Address for the Constant table Programmable Pointer Register 1(CTPPR_1) > #define CTPPR_1 0x2202C > > > .macro LD32 > .mparam dst,src > LBBO dst,src,#0x00,4 > .endm > > .macro LD16 > .mparam dst,src > LBBO dst,src,#0x00,2 > .endm > > .macro LD8 > .mparam dst,src > LBBO dst,src,#0x00,1 > .endm > > .macro ST32 > .mparam src,dst > SBBO src,dst,#0x00,4 > .endm > > .macro ST16 > .mparam src,dst > SBBO src,dst,#0x00,2 > .endm > > .macro ST8 > .mparam src,dst > SBBO src,dst,#0x00,1 > .endm > > > // *************************************** > // * Global Structure Definitions * > // *************************************** > > .struct Global > .u32 regPointer > .u32 regVal > .ends > > > // *************************************** > // * Global Register Assignments * > // *************************************** > > .assign Global, r2, *, global > > #endif //_PRU_memAccess_DDR_PRUsharedRAM_ > > -- For more options, visit http://beagleboard.org/discuss --- You received this message because you are subscribed to the Google Groups "BeagleBoard" group. To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.