通过 /dev/mem 读取 Beaglebone Black ADC

问题描述

我正在尝试编写一个 C 程序来读取 Beaglebone Black 上的 ADC。我知道我可以使用 sysfs 方式...但我想看看是否有可能获得与 /dev/mem 映射物理地址空间相同的结果。

我有一个文件 am335x.h,内容如下:

#ifndef _AM335X_H_
#define _AM335X_H_

#define MMAP_OFFSET (0x44C00000)
#define MMAP_SIZE   (0x481AEFFF-MMAP_OFFSET)

/* Clock Module Memory Registers */
#define CM_WKUP (0x44E00400)
#define CM_WKUP_ADC_TSC_CLKCTRL (CM_WKUP+0xBC)
#define CM_WKUP_MODULEMODE_ENABLE (0x02)
#define CM_WKUP_IDLEST_disABLED (0x03<<16)

#define CM_PER (0x44E00000)
#define CM_PER_EPWMSS1_CLKCTRL (CM_PER+0xCC)
#define CM_PER_EPWMSS0_CLKCTRL (CM_PER+0xD4)
#define CM_PER_EPWMSS2_CLKCTRL (CM_PER+0xD8)


/* GPIO Memory Registers */
#define GPIO_REGISTER_SIZE (4)

#define GPIO0   (0x44E07000)
#define GPIO1       (0x4804C000)
#define GPIO2       (0x481AC000)
#define GPIO3       (0x481AE000)

#define GPIO_CLEARDATAOUT (0x190)
#define GPIO_SETDATAOUT   (0x194)
#define GPIO_OE               (0x134)
#define GPIO_DATAOUT      (0x13C)
#define GPIO_DATAIN       (0x138)

/* Analog Digital Converter Memory Registers */
#define ADC_TSC (0x44E0D000)

#define ADC_CTRL (ADC_TSC+0x40)
#define ADC_STEPCONfig_WRITE_PROTECT_OFF (0x01<<2)
#define ADC_STEPENABLE (ADC_TSC+0x54)

#define ADCSTEPCONfig1 (ADC_TSC+0x64)
#define ADCSTEPDELAY1  (ADC_TSC+0x68)
#define ADCSTEPCONfig2 (ADC_TSC+0x6C)
#define ADCSTEPDELAY2  (ADC_TSC+0x70)
#define ADCSTEPCONfig3 (ADC_TSC+0x74)
#define ADCSTEPDELAY3  (ADC_TSC+0x78)
#define ADCSTEPCONfig4 (ADC_TSC+0x7C)
#define ADCSTEPDELAY4  (ADC_TSC+0x80)
#define ADCSTEPCONfig5 (ADC_TSC+0x84)
#define ADCSTEPDELAY5  (ADC_TSC+0x88)
#define ADCSTEPCONfig6 (ADC_TSC+0x8C)
#define ADCSTEPDELAY6  (ADC_TSC+0x90)
#define ADCSTEPCONfig7 (ADC_TSC+0x94)
#define ADCSTEPDELAY7  (ADC_TSC+0x98)
#define ADCSTEPCONfig8 (ADC_TSC+0x9C)
#define ADCSTEPDELAY8  (ADC_TSC+0xA0)

#define ADC_AVG0  (0x000)
#define ADC_AVG2  (0x001)
#define ADC_AVG4  (0x010)
#define ADC_AVG8  (0x011)
#define ADC_AVG16 (0x100) 

#define ADC_FIFO0DATA (ADC_TSC+0x100)
#define ADC_FIFO_MASK (0xFFF)

typedef struct s_PWM {
  char muxmode; /*!< mux mode,0-7,see am335x technical manual */
  char *name;   /*!< name of pwm pin,i.e.: "EHRPWM2B" */
  char *path;   /*!< path to the pwm,i.e.: "ehrpwm.2:1" */
} PWM;

typedef struct s_PIN {
  char *name;   /*!< readable name of pin,i.e.: "GPIO1_21",see beaglebone user guide */
  unsigned int gpio_bank; /*!< which of the four gpio banks is this pin in,i.e.: GPIO1,r 0x4804C000 */
  uint8_t gpio; /*!< pin number on the am335x processor */
  uint8_t bank_id; /*!< pin number within each bank,should be 0-31 */
  char *mux;    /*!< file name for setting mux */
  uint8_t eeprom; /*!< position in eeprom */
  unsigned char pwm_present; /*!< whether or not this pin can be used for PWM */
  PWM pwm;      /*!< pwm struct if pwm_present is true */

} PIN;

#define TRUE 1
#define FALSE 0

#define USR0  ((PIN){     "GPIO1_21",GPIO1,21,"",FALSE,0   })
#define USR1  ((PIN){     "GPIO1_22",22,0   })
#define USR2  ((PIN){     "GPIO1_23",23,0   })
#define USR3  ((PIN){     "GPIO1_24",24,0   })
#define P8_3  ((PIN){   "GPIO1_6",38,6,"gpmc_ad6",26,0   })
#define P8_4  ((PIN){   "GPIO1_7",39,7,"gpmc_ad7",27,0   })
#define P8_5  ((PIN){   "GPIO1_2",34,2,"gpmc_ad2",0   })
#define P8_6  ((PIN){   "GPIO1_3",35,3,"gpmc_ad3",0   })
#define P8_7  ((PIN){   "TIMER4",GPIO2,66,"gpmc_advn_ale",41,0   })
#define P8_8  ((PIN){   "TIMER7",67,"gpmc_oen_ren",44,0   })
#define P8_9  ((PIN){   "TIMER5",69,5,"gpmc_ben0_cle",42,0   })
#define P8_10 ((PIN){   "TIMER6",68,4,"gpmc_wen",43,0   })
#define P8_11 ((PIN){   "GPIO1_13",45,13,"gpmc_ad13",29,0   })
#define P8_12 ((PIN){   "GPIO1_12",12,"gpmc_ad12",28,0   })
#define P8_13 ((PIN){   "EHRPWM2B",GPIO0,"gpmc_ad9",15,TRUE,(PWM){4,"EHRPWM2B","ehrpwm.2:1"}})
#define P8_14 ((PIN){   "GPIO0_26","gpmc_ad10",16,0   })
#define P8_15 ((PIN){   "GPIO1_15",47,"gpmc_ad15",31,0   })
#define P8_16 ((PIN){   "GPIO1_14",46,14,"gpmc_ad14",30,0   })
#define P8_17 ((PIN){   "GPIO0_27","gpmc_ad11",17,0   })
#define P8_18 ((PIN){   "GPIO2_1",65,1,"gpmc_clk",40,0   })
#define P8_19 ((PIN){   "EHRPWM2A","gpmc_ad8","EHRPWM2A","ehrpwm.2:0"}})
#define P8_20 ((PIN){   "GPIO1_31",63,"gpmc_csn2",0   })
#define P8_21 ((PIN){   "GPIO1_30",62,"gpmc_csn1",0   })
#define P8_22 ((PIN){   "GPIO1_5",37,"gpmc_ad5",25,0   })
#define P8_23 ((PIN){   "GPIO1_4",36,"gpmc_ad4",0   })
#define P8_24 ((PIN){   "GPIO1_1",33,"gpmc_ad1",0   })
#define P8_25 ((PIN){   "GPIO1_0",32,"gpmc_ad0",20,0   })
#define P8_26 ((PIN){   "GPIO1_29",61,"gpmc_csn0",0   })
#define P8_27 ((PIN){   "GPIO2_22",86,"lcd_vsync",57,0   })
#define P8_28 ((PIN){   "GPIO2_24",88,"lcd_pclk",59,0   })
#define P8_29 ((PIN){   "GPIO2_23",87,"lcd_hsync",58,0   })
#define P8_30 ((PIN){   "GPIO2_25",89,"lcd_ac_bias_en",60,0   })
#define P8_31 ((PIN){   "UART5_CTSN",10,"lcd_data14",0   })
#define P8_32 ((PIN){   "UART5_RTSN",11,"lcd_data15",8,0   })
#define P8_33 ((PIN){   "UART4_RTSN",9,"lcd_data13",0   })
#define P8_34 ((PIN){   "UART3_RTSN",81,"lcd_data11",56,(PWM){2,"EHRPWM1B","ehrpwm.1:1"}})
#define P8_35 ((PIN){   "UART4_CTSN","lcd_data12",0   })
#define P8_36 ((PIN){   "UART3_CTSN",80,"lcd_data10",55,"EHRPWM1A","ehrpwm.1:0"}})
#define P8_37 ((PIN){   "UART5_TXD",78,"lcd_data8",53,0   })
#define P8_38 ((PIN){   "UART5_RXD",79,"lcd_data9",54,0   })
#define P8_39 ((PIN){   "GPIO2_12",76,"lcd_data6",51,0   })
#define P8_40 ((PIN){   "GPIO2_13",77,"lcd_data7",52,0   })
#define P8_41 ((PIN){   "GPIO2_10",74,"lcd_data4",49,0   })
#define P8_42 ((PIN){   "GPIO2_11",75,"lcd_data5",50,0   })
#define P8_43 ((PIN){   "GPIO2_8",72,"lcd_data2",0   })
#define P8_44 ((PIN){   "GPIO2_9",73,"lcd_data3",48,0   })
#define P8_45 ((PIN){   "GPIO2_6",70,"lcd_data0",(PWM){3,"ehrpwm.2:0"}})
#define P8_46 ((PIN){   "GPIO2_7",71,"lcd_data1","ehrpwm.2:1"}})

#define P9_11 ((PIN){   "UART4_RXD","gpmc_wait0",18,0})
#define P9_12 ((PIN){   "GPIO1_28","gpmc_ben1",0})
#define P9_13 ((PIN){   "UART4_TXD","gpmc_wpn",19,0})
#define P9_14 ((PIN){   "EHRPWM1A","gpmc_a2",(PWM){6,"ehrpwm.1:0"}})
#define P9_15 ((PIN){   "GPIO1_16","mii1_rxd3",0})
#define P9_16 ((PIN){   "EHRPWM1B","gpmc_a3","ehrpwm.1:1"}})
#define P9_17 ((PIN){   "I2C1_SCL","spi0_cs0",0})
#define P9_18 ((PIN){   "I2C1_SDA","spi0_d1",0})
#define P9_19 ((PIN){   "I2C2_SCL","uart1_rtsn",0})
#define P9_20 ((PIN){   "I2C2_SDA","uart1_ctsn",0})
#define P9_21 ((PIN){   "UART2_TXD","spi0_d0","EHRPWM0B","ehrpwm.0:1"}})
#define P9_22 ((PIN){   "UART2_RXD","spi0_sclk","EHRPWM0A","ehrpwm.0:0"}})
#define P9_23 ((PIN){   "GPIO1_17","gpmc_a1",0})
#define P9_24 ((PIN){   "UART1_TXD","uart1_txd",0})
#define P9_25 ((PIN){   "GPIO3_21",GPIO3,117,"mcasp0_ahclkx",0})
#define P9_26 ((PIN){   "UART1_RXD","uart1_rxd",0})
#define P9_27 ((PIN){   "GPIO3_19",115,"mcasp0_fsr",64,0})
#define P9_28 ((PIN){   "SPI1_CS0",113,"mcasp0_ahclkr","ECAPPWM2","ecap.2"}})
#define P9_29 ((PIN){   "SPI1_D0",111,"mcasp0_fsx",(PWM){1,"ehrpwm.0:1"}})
#define P9_30 ((PIN){   "SPI1_D1",112,"mcasp0_axr0",0})
#define P9_31 ((PIN){   "SPI1_SCLK",110,"mcasp0_aclkx","ehrpwm.0:0"}})
#define P9_33 ((PIN){   "AIN4",0})
#define P9_35 ((PIN){   "AIN6",0})
#define P9_36 ((PIN){   "AIN5",0})
#define P9_37 ((PIN){   "AIN2",0})
#define P9_38 ((PIN){   "AIN3",0})
#define P9_39 ((PIN){   "AIN0",0})
#define P9_40 ((PIN){   "AIN1",0})
#define P9_41 ((PIN){   "CLKOUT2","xdma_event_intr1",0})
#define P9_42 ((PIN){   "GPIO0_7","ecap0_in_pwm0_out",(PWM){0,"ECAPPWM0","ecap.0"}})


#define INPUT    ((unsigned char)(1))
#define OUTPUT   ((unsigned char)(0))
#define PULLUP   ((unsigned char)(1))
#define PULLDOWN ((unsigned char)(0))
#define disABLED ((unsigned char)(2))

#define CONfig_MUX_PATH "/sys/kernel/debug/omap_mux"



#endif

然后我有了我的 C 程序,ADC_mapping.c:

#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>  
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
//#include <inttypes.h>
#include "am335x.h"


static volatile uint32_t *map;
static char mapped = FALSE;

// Function declaration

int init();
int adc_init();
int analogRead(PIN p);

// Main function
int main()
{
        
        uint32_t adc0;
        int count = 0;

        while(count <= 1000)
        {
                adc0 = analogRead(P9_39);  
                printf("Value AIN0: %zu \n",adc0); 
                usleep (50000);                  
        }


        return  0;
}

/**
 * map /dev/mem to memory
 *
 * @returns whether or not the mapping of /dev/mem into memory was successful
 */
int init() {
        if(!mapped) {
                int fd;
                fd = open("/dev/mem",O_RDWR);
                if(fd == -1) {
                        perror("Unable to open /dev/mem");
                        exit(EXIT_FAILURE);
                }
                map = (uint32_t*)mmap(NULL,MMAP_SIZE,PROT_READ | PROT_WRITE,MAP_SHARED,fd,MMAP_OFFSET);
                if(map == MAP_Failed) {
                        close(fd);
                        perror("Unable to map /dev/mem");
                        exit(EXIT_FAILURE);
                }
                mapped = TRUE;
        }
        return mapped;
}

/**
 * Initializee the Analog-Digital Converter
 */
int adc_init() {
        init();

        // enable the CM_WKUP_ADC_TSC_CLKCTRL with CM_WKUP_MODUELEMODE_ENABLE
        map[(CM_WKUP_ADC_TSC_CLKCTRL-MMAP_OFFSET)/4] |= CM_WKUP_MODULEMODE_ENABLE;

        // wait for the enable to complete
        while(!(map[(CM_WKUP_ADC_TSC_CLKCTRL-MMAP_OFFSET)/4] & CM_WKUP_MODULEMODE_ENABLE)) {
                // waiting for adc clock module to initialize
                //printf("Waiting for CM_WKUP_ADC_TSC_CLKCTRL to enable with MODULEMODE_ENABLE\n");
        }
        // software reset,set bit 1 of sysconfig high?
        // make sure STEPCONfig write protect is off
        map[(ADC_CTRL-MMAP_OFFSET)/4] |= ADC_STEPCONfig_WRITE_PROTECT_OFF;

        // set up each ADCSTEPCONfig for each ain pin
        map[(ADCSTEPCONfig1-MMAP_OFFSET)/4] = 0x00<<19 | ADC_AVG16;
        map[(ADCSTEPDELAY1-MMAP_OFFSET)/4]  = (0x0F)<<24;
        map[(ADCSTEPCONfig2-MMAP_OFFSET)/4] = 0x01<<19 | ADC_AVG16;
        map[(ADCSTEPDELAY2-MMAP_OFFSET)/4]  = (0x0F)<<24;
        map[(ADCSTEPCONfig3-MMAP_OFFSET)/4] = 0x02<<19 | ADC_AVG16;
        map[(ADCSTEPDELAY3-MMAP_OFFSET)/4]  = (0x0F)<<24;
        map[(ADCSTEPCONfig4-MMAP_OFFSET)/4] = 0x03<<19 | ADC_AVG16;
        map[(ADCSTEPDELAY4-MMAP_OFFSET)/4]  = (0x0F)<<24;
        map[(ADCSTEPCONfig5-MMAP_OFFSET)/4] = 0x04<<19 | ADC_AVG16;
        map[(ADCSTEPDELAY5-MMAP_OFFSET)/4]  = (0x0F)<<24;
        map[(ADCSTEPCONfig6-MMAP_OFFSET)/4] = 0x05<<19 | ADC_AVG16;
        map[(ADCSTEPDELAY6-MMAP_OFFSET)/4]  = (0x0F)<<24;
        map[(ADCSTEPCONfig7-MMAP_OFFSET)/4] = 0x06<<19 | ADC_AVG16;
        map[(ADCSTEPDELAY7-MMAP_OFFSET)/4]  = (0x0F)<<24;
        map[(ADCSTEPCONfig8-MMAP_OFFSET)/4] = 0x07<<19 | ADC_AVG16;
        map[(ADCSTEPDELAY8-MMAP_OFFSET)/4]  = (0x0F)<<24;

        // enable the ADC
        map[(ADC_CTRL-MMAP_OFFSET)/4] |= 0x01;
}

/**
 * Read in from an analog pin
 *
 * @param p pin to read value from
 * @returns the analog value of pin p
 */
int analogRead(PIN p) {
        init();
        
        // the clock module is not enabled
        if(map[(CM_WKUP_ADC_TSC_CLKCTRL-MMAP_OFFSET)/4] & CM_WKUP_IDLEST_disABLED)
                adc_init();
        
        // enable the step sequencer for this pin
        map[(ADC_STEPENABLE-MMAP_OFFSET)/4] |= (0x01<<(p.bank_id+1));

        // return the the FIFO0 data register
        return map[(ADC_FIFO0DATA-MMAP_OFFSET)/4] & ADC_FIFO_MASK;
}

输出为: Output

但是应该读取的值是: this

知道原因吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)