#include #include #include #include #include #include #include #include #include #include #include "asm/uaccess.h" #include #include "com_gpio.h" #include "stm32f4xx.h" #include "stm32_hal_legacy.h" #include "stm32f4xx_hal_spi.h" #include "stm32f4xx_hal_gpio.h" #include "driver.h" static int major = MAJOR_SPI; static int ret=0; #define DEVNAME "spi" #define NUM_OF_DEVICES 6 struct spi_device { dev_t devno; struct cdev cdev; char name[16]; //IRQn_Type Event_IRQn; //IRQn_Type Err_IRQn; } spi_dev[NUM_OF_DEVICES]; SPI_HandleTypeDef hspi1, hspi2, hspi3, hspi4, hspi5, hspi6; static int spi_open(struct inode *inode, struct file *filep); static int spi_close(struct inode *inode, struct file *filep); static ssize_t spi_read(struct file *filep, char __user *buf, size_t size, loff_t *offset); static ssize_t spi_write(struct file *filep, const char __user *buf, size_t size, loff_t *offset); static int spi_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); static struct file_operations spi_ops = { .owner = THIS_MODULE, .open = spi_open, .release = spi_close, .ioctl = spi_ioctl, .read = spi_read, .write = spi_write, }; static int spi_open(struct inode *inode, struct file *filep) { SPI_HandleTypeDef *pHspi; int imajor,iminor; imajor = MAJOR(inode->i_rdev); iminor = MINOR(inode->i_rdev); if(imajor != major) { printk("Error: %s %d spi major fail! %d\n",__FILE__,__LINE__,imajor); return -1; } //printk("---> open major=%d, minor=%d\n",imajor,iminor); switch(iminor) { case 0: pHspi = &hspi1; break; case 1: pHspi = &hspi2; break; case 2: pHspi = &hspi3; break; case 3: pHspi = &hspi4; break; case 4: pHspi = &hspi5; break; case 5: pHspi = &hspi6; break; default: printk("Error:%s %d Invalid minor %d",__FILE__,__LINE__,iminor); return -1; } __HAL_SPI_ENABLE(pHspi); return 0; } static int spi_close(struct inode *inode, struct file *filep) { SPI_HandleTypeDef *pHspi; int imajor,iminor; imajor = MAJOR(inode->i_rdev); iminor = MINOR(inode->i_rdev); if(imajor != major) { printk("Error: %s %d spi major fail! %d\n",__FILE__,__LINE__,imajor); return -1; } //printk("---> close major=%d, minor=%d\n",imajor,iminor); switch(iminor) { case 0: pHspi = &hspi1; break; case 1: pHspi = &hspi2; break; case 2: pHspi = &hspi3; break; case 3: pHspi = &hspi4; break; case 4: pHspi = &hspi5; break; case 5: pHspi = &hspi6; break; default: printk("Error:%s %d Invalid minor %d",__FILE__,__LINE__,iminor); return -1; } __HAL_SPI_DISABLE(pHspi); return 0; } static int spi_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) { HAL_StatusTypeDef ret = HAL_OK; spi_arg_t spi_args; int imajor,iminor; SPI_HandleTypeDef *pHspi; int i; imajor = MAJOR(inode->i_rdev); iminor = MINOR(inode->i_rdev); if(imajor != MAJOR_SPI) { printk("Error: %s %d spi major fail! %d\n",__FILE__,__LINE__,imajor); return -EFAULT; } switch(iminor) { case 0: pHspi = &hspi1; break; case 1: pHspi = &hspi2; break; case 2: pHspi = &hspi3; break; case 3: pHspi = &hspi4; break; case 4: pHspi = &hspi5; break; case 5: pHspi = &hspi6; break; default: printk("Error:%s %d Invalid minor %d",__FILE__,__LINE__,iminor); return -1; } if ( copy_from_user(&spi_args, (void*)arg, sizeof(spi_arg_t)) != 0) { printk("---> copy form user space fail!\n"); return -1; } switch(cmd) { case SPI_MASTER_TRANSFER: // printk("SPI%d_transfer %d: ", iminor+1, spi_args.Size); // for(i=0;i copy to user space fail!\n"); return -1; } break; default: printk("---> Invalid action\n"); ret = -1; break; } return ret; } static ssize_t spi_read(struct file *filep, char __user *buf, size_t size, loff_t *offset) { return 0; } static ssize_t spi_write(struct file *filep, const char __user *buf, size_t size, loff_t *offset) { return 0; } void spi_hw_init(void) { GPIO_InitTypeDef spi_gpio; //SPI1 //SPI2 __HAL_RCC_GPIOI_CLK_ENABLE(); spi_gpio.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3; spi_gpio.Mode = GPIO_MODE_AF_PP; spi_gpio.Pull = GPIO_PULLUP; spi_gpio.Speed = GPIO_SPEED_FREQ_HIGH; spi_gpio.Alternate = GPIO_AF5_SPI2; HAL_GPIO_Init(GPIOI, &spi_gpio); //NSS HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_SET); spi_gpio.Pin = GPIO_PIN_0; spi_gpio.Mode = GPIO_MODE_OUTPUT_PP; spi_gpio.Pull = GPIO_PULLUP; spi_gpio.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOI, &spi_gpio); __HAL_RCC_SPI2_CLK_ENABLE(); hspi2.Instance = SPI2; hspi2.Init.Direction = SPI_DIRECTION_2LINES; hspi2.Init.Mode = SPI_MODE_MASTER; hspi2.Init.DataSize = SPI_DATASIZE_8BIT; hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH; hspi2.Init.CLKPhase = SPI_PHASE_2EDGE; hspi2.Init.NSS = SPI_NSS_SOFT; hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi2.Init.TIMode = SPI_TIMODE_DISABLE; hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi2.Init.CRCPolynomial = 0; HAL_SPI_Init(&hspi2); //SPI3 //SPI4 //SPI5 __HAL_RCC_GPIOF_CLK_ENABLE(); spi_gpio.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9; spi_gpio.Mode = GPIO_MODE_AF_PP; spi_gpio.Pull = GPIO_PULLUP; spi_gpio.Speed = GPIO_SPEED_FREQ_HIGH; spi_gpio.Alternate = GPIO_AF5_SPI5; HAL_GPIO_Init(GPIOF, &spi_gpio); //NSS HAL_GPIO_WritePin(GPIOF, GPIO_PIN_6, GPIO_PIN_SET); spi_gpio.Pin = GPIO_PIN_6; spi_gpio.Mode = GPIO_MODE_OUTPUT_PP; spi_gpio.Pull = GPIO_PULLUP; spi_gpio.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOF, &spi_gpio); __HAL_RCC_SPI5_CLK_ENABLE(); hspi5.Instance = SPI5; hspi5.Init.Direction = SPI_DIRECTION_2LINES; hspi5.Init.Mode = SPI_MODE_MASTER; hspi5.Init.DataSize = SPI_DATASIZE_8BIT; hspi5.Init.CLKPolarity = SPI_POLARITY_HIGH; hspi5.Init.CLKPhase = SPI_PHASE_2EDGE; hspi5.Init.NSS = SPI_NSS_SOFT; hspi5.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; hspi5.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi5.Init.TIMode = SPI_TIMODE_DISABLE; hspi5.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi5.Init.CRCPolynomial = 0; HAL_SPI_Init(&hspi5); //SPI6 } static int __init spi_init(void) { int ret; //SPI1 //SPI2 printk("spi2 module start ...\n"); spi_dev[1].devno = MKDEV(MAJOR_SPI, 1); sprintf(spi_dev[1].name, "%s%d", DEVNAME, 2); register_chrdev_region(spi_dev[1].devno, 1, spi_dev[1].name); cdev_add(&spi_dev[1].cdev, spi_dev[1].devno, 1); cdev_init(&spi_dev[1].cdev, &spi_ops); //SPI3 //SPI4 //SPI5 printk("spi5 module start ...\n"); spi_dev[4].devno = MKDEV(MAJOR_SPI, 4); sprintf(spi_dev[4].name, "%s%d", DEVNAME, 5); register_chrdev_region(spi_dev[4].devno, 1, spi_dev[4].name); cdev_add(&spi_dev[4].cdev, spi_dev[4].devno, 1); cdev_init(&spi_dev[4].cdev, &spi_ops); //SPI6 spi_hw_init(); return 0; ERR_STEP1: unregister_chrdev_region(spi_dev[1].devno, 1); unregister_chrdev_region(spi_dev[4].devno, 1); ERR_STEP: cdev_del(&spi_dev[1].cdev); cdev_del(&spi_dev[4].cdev); return ret; } static void __exit spi_exit(void) { unregister_chrdev_region(spi_dev[1].devno,1); cdev_del(&spi_dev[1].cdev); unregister_chrdev_region(spi_dev[4].devno,1); cdev_del(&spi_dev[4].cdev); } module_init(spi_init); module_exit(spi_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("jimbo"); MODULE_DESCRIPTION("this is spi module");