/* include path: install_root/linux/include */ #include #include #include #include #include #include #include #include #include #include #include #include #include "stm32f4xx.h" #include "stm32f4xx_hal_rcc.h" #include "stm32f4xx_hal_gpio.h" #include "stm32f4xx_hal_adc.h" #include "stm32f4xx_hal_dma.h" #include "driver.h" #include "stm32_hal_legacy.h" //static dev_t devno; //static struct cdev *adc_cdev = NULL; //static int count = 3; #define NUM_OF_DEVICES 3 //ruct class *my_class = NULL; //struct device *dev = NULL; #define DEVNAME "adc" struct adc_device { dev_t devno; struct cdev cdev; char data[128]; char name[16]; IRQn_Type DMA_IRQn; } adc_dev[NUM_OF_DEVICES]; uint16_t gAdc1Value[10][7]; static int adc_open(struct inode *inode, struct file *filep); static int adc_close(struct inode *inode, struct file *filep); static ssize_t adc_read(struct file *filep, char __user *buf, size_t size, loff_t *offset); static ssize_t adc_write(struct file *filep, const char __user *buf, size_t size, loff_t *offset); static int adc_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); static struct file_operations adc_ops = { .owner = THIS_MODULE, .open = adc_open, .release = adc_close, .read = adc_read, .write = adc_write, .ioctl = adc_ioctl, }; static int adc_open(struct inode *inode, struct file *filep) { return 0; } static int adc_close(struct inode *inode, struct file *filep) { //__HAL_ADC_DISABLE(&handle_adc); return 0; } static ssize_t adc_read(struct file *filep, char __user *buf, size_t size, loff_t *offset) { //printk("fmc_read!\n"); return 0; } static ssize_t adc_write(struct file *filep, const char __user *buf, size_t size, loff_t *offset) { return 0; } static int adc_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) { int i; adc_arg_t adc_arg; if ( copy_from_user((void*)&adc_arg, (void*)arg, 1) ) return -EFAULT; if((adc_arg.channel < 1) || (adc_arg.channel > 7)) return -EFAULT; switch(cmd) { case ADC_GET_RESULT: for(i=0;i<10;i++) adc_arg.value[i] = gAdc1Value[i][adc_arg.channel-1]; copy_to_user((void*)arg, (void*)&adc_arg, sizeof(adc_arg_t)); break; default: printk("Invalid command!\n"); break; } return 0; } ADC_HandleTypeDef hadc; DMA_HandleTypeDef hdma_adc; // /** // * @brief Handles DMA interrupt request. // * @param hdma pointer to a DMA_HandleTypeDef structure that contains // * the configuration information for the specified DMA Stream. // * @retval None // */ // irqreturn_t HAL_DMA_IRQHandler(int irqno, void *dev_id ) // { // return IRQ_HANDLED; // } int adc_hw_init(void) { ADC_ChannelConfTypeDef sConfig; GPIO_InitTypeDef GPIO_InitStruct; /* ADC1 * PA0 - ADC1_IN0 * PA3 - ADC1_IN3 * PA4 - ADC1_IN4 * PA5 - ADC1_IN5 * PA6 - ADC1_IN6 * PB0 - ADC1_IN8 * PB1 - ADC1_IN9 */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); __HAL_RCC_ADC1_CLK_ENABLE(); hadc.Instance = ADC1; hadc.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV8; hadc.Init.Resolution = ADC_RESOLUTION_12B; hadc.Init.ScanConvMode = ENABLE; hadc.Init.ContinuousConvMode = ENABLE; hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.NbrOfDiscConversion = 0; //hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.NbrOfConversion = 7; hadc.Init.DMAContinuousRequests = ENABLE; hadc.Init.EOCSelection = DISABLE; if(HAL_ADC_Init(&hadc) != HAL_OK) { printk(KERN_ERR"adc hw init error!\n"); } sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; sConfig.Offset = 0; sConfig.Rank = 1; sConfig.Channel = ADC_CHANNEL_0; if(HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) { printk(KERN_ERR"adc channel3 init error!\n"); } sConfig.Rank = 2; sConfig.Channel = ADC_CHANNEL_3; if(HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) { printk(KERN_ERR"adc channel3 init error!\n"); } sConfig.Rank = 3; sConfig.Channel = ADC_CHANNEL_4; if(HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) { printk(KERN_ERR"adc channel4 init error!\n"); } sConfig.Rank = 4; sConfig.Channel = ADC_CHANNEL_5; if(HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) { printk(KERN_ERR"adc channel5 init error!\n"); } sConfig.Rank = 5; sConfig.Channel = ADC_CHANNEL_6; if(HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) { printk(KERN_ERR"adc channel6 init error!\n"); } sConfig.Rank = 6; sConfig.Channel = ADC_CHANNEL_8; if(HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) { printk(KERN_ERR"adc channel3 init error!\n"); } sConfig.Rank = 7; sConfig.Channel = ADC_CHANNEL_9; if(HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) { printk(KERN_ERR"adc channel3 init error!\n"); } // __HAL_ADC_ENABLE(&hadc); // config dma __HAL_RCC_DMA2_CLK_ENABLE(); hdma_adc.Instance = DMA2_Stream0; hdma_adc.Init.Channel = DMA_CHANNEL_0; hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc.Init.MemInc = DMA_MINC_ENABLE; hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_adc.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_adc.Init.Mode = DMA_CIRCULAR; hdma_adc.Init.Priority = DMA_PRIORITY_LOW; hdma_adc.Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma_adc.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL; hdma_adc.Init.MemBurst = DMA_MBURST_SINGLE; hdma_adc.Init.PeriphBurst = DMA_PBURST_SINGLE; HAL_DMA_Init(&hdma_adc); /* Associate the initialized DMA handle to the the ADC handle */ __HAL_LINKDMA(&hadc, DMA_Handle, hdma_adc); return 0; } static int __init adc_init(void) { printk("adc1 module start...\n"); //ADC1 adc_dev[0].devno = MKDEV(MAJOR_ADC, 0); sprintf(adc_dev[0].name, "%s%d", DEVNAME, 1); register_chrdev_region(adc_dev[0].devno, 1, adc_dev[0].name); cdev_add(&adc_dev[0].cdev, adc_dev[0].devno, 1); cdev_init(&adc_dev[0].cdev, &adc_ops); //ADC2 //ADC3 if(adc_hw_init() != 0) goto ERR_STEP1; // adc_dev[0].DMA_IRQn = DMA2_Stream0_IRQn; // adc_dev[1].DMA_IRQn = DMA2_Stream2_IRQn; // adc_dev[2].DMA_IRQn = DMA2_Stream1_IRQn; // // register adc1 interrupt // ret = request_irq(adc_dev[0].DMA_IRQn, HAL_DMA_IRQHandler, IRQF_SHARED, adc_dev[0].name, &adc_dev[0].devno); // if(ret) { // printk("request_irq() fialed! %d\n", ret); // goto ERR_STEP1; // } // HAL_ADC_Start(&hadc); // HAL_DMA_Start(&hdma_adc, (uint32_t)&hadc.Instance->DR, (uint16_t*)&gAdc1Value, 40); if(HAL_ADC_Start_DMA(&hadc, (uint32_t*)gAdc1Value, 70) != HAL_OK) { printk("Start DMA error!"); } // ADC_Common_TypeDef * adc_commonReg = ADC123_COMMON; // printk("adc adc driver init over!, CCR = %#x\n", adc_commonReg->CCR); // printk("adc CR1: %#x, CR2: %#x\n", hadc.Instance->CR1, hadc.Instance->CR2); return 0; ERR_STEP1: unregister_chrdev_region(adc_dev[0].devno, 1); //ERR_STEP: cdev_del(&adc_dev[0].cdev); return 0; } static void __exit adc_exit(void) { unregister_chrdev_region(adc_dev[0].devno, 1); cdev_del(&adc_dev[0].cdev); } module_init(adc_init); module_exit(adc_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("jimbo_zhang"); MODULE_DESCRIPTION("adc driver");