#include #include #include #include #include #include #include #include #include #include #include "asm/uaccess.h" #include #include "spi.h" #include "./stm32f429_spi.h" static int major = MAJOR_SPI; static int minor = 0; static dev_t devno; static struct cdev *spi_cdev = NULL; static int count = 6; static int ret=0; #define DEVNAME "spi" #define SPIT_FLAG_TIMEOUT ((uint32_t)0x1000) #define SPIT_LONG_TIMEOUT ((uint32_t)(10 * I2CT_FLAG_TIMEOUT)) int iic_read_byte(void); 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, }; SPI_DEV_T spi[] = {{.bus = SPI1,},{.bus = SPI2,},{.bus = SPI3,},{.bus = SPI4,},{.bus = SPI5,},{.bus = SPI6,}}; static int spi_open(struct inode *inode, struct file *filep) { 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: /* Enable SPI peripheral */ SPI_Cmd(SPI1,ENABLE); break; case 1: /* Enable I2C peripheral */ SPI_Cmd(SPI2,ENABLE); break; case 2: /* Enable I2C peripheral */ SPI_Cmd(SPI3,ENABLE); break; case 3: /* Enable I2C peripheral */ SPI_Cmd(SPI4,ENABLE); break; case 4: /* Enable I2C peripheral */ SPI_Cmd(SPI5,ENABLE); break; case 5: /* Enable I2C peripheral */ SPI_Cmd(SPI6,ENABLE); break; default: printk("Error:%s %d Invalid minor %d",__FILE__,__LINE__,iminor); return -1; } return 0; } static int spi_close(struct inode *inode, struct file *filep) { 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; } switch(iminor) { case 0: /* Disable SPI peripheral */ SPI_Cmd(SPI1,DISABLE); break; case 1: /* Disable I2C peripheral */ SPI_Cmd(SPI2,DISABLE); break; case 2: /* Disable SPI peripheral */ SPI_Cmd(SPI3,DISABLE); break; case 3: /* Disable SPI peripheral */ SPI_Cmd(SPI4,DISABLE); break; case 4: /* Disable SPI peripheral */ SPI_Cmd(SPI5,DISABLE); break; case 5: /* Disable SPI peripheral */ SPI_Cmd(SPI6,DISABLE); break; default: printk("Error:%s %d Invalid minor %d",__FILE__,__LINE__,iminor); return -1; } return 0; } static int spi_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) { SPI_DEV_T spi_dev; int read_data=0; ret = 0; if ( copy_from_user(&spi_dev, (void*)arg, sizeof(SPI_DEV_T)) != 0) { printk("---> copy form user space fail!\n"); return -1; } switch(cmd) { // case SET_I2C_ADDR: // printk("---> set i2c addr.\n"); // i2c_dev.bus->OAR1 = i2c_dev.ownAddr; break; // case GENERATE_STOP: // I2C_GenerateSTOP(i2c_dev.bus, ENABLE); break; default: printk("---> Invalid action\n"); return -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_config_init() { GPIO_InitTypeDef spi_gpio; SPI_InitTypeDef spi; //gpio init RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI5,ENABLE); spi_gpio.GPIO_OType=GPIO_OType_PP; spi_gpio.GPIO_PuPd=GPIO_PuPd_UP; spi_gpio.GPIO_Speed=GPIO_Speed_50MHz; spi_gpio.GPIO_Mode=GPIO_Mode_AF; spi_gpio.GPIO_Pin=GPIO_Pin_7; GPIO_Init(GPIOF, &spi_gpio); GPIO_PinAFConfig(GPIOF, GPIO_PinSource7, GPIO_AF_SPI5); spi_gpio.GPIO_Pin=GPIO_Pin_8; GPIO_Init(GPIOF, &spi_gpio); GPIO_PinAFConfig(GPIOF, GPIO_PinSource8, GPIO_AF_SPI5); spi_gpio.GPIO_Pin=GPIO_Pin_9; GPIO_Init(GPIOF, &spi_gpio); GPIO_PinAFConfig(GPIOF, GPIO_PinSource9, GPIO_AF_SPI5); spi_gpio.GPIO_Mode=GPIO_Mode_OUT; spi_gpio.GPIO_Pin=GPIO_Pin_6; GPIO_Init(GPIOF, &spi_gpio); GPIO_SetBits(GPIOF,GPIO_Pin_6); //spi config init spi.SPI_Direction=SPI_Direction_2Lines_FullDuplex; spi.SPI_Mode=SPI_Mode_Master; spi.SPI_DataSize=SPI_DataSize_8b; spi.SPI_CPOL=SPI_CPOL_High; spi.SPI_CPHA=SPI_CPHA_2Edge; spi.SPI_NSS=SPI_NSS_Soft; spi.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_2; spi.SPI_FirstBit=SPI_FirstBit_MSB; spi.SPI_CRCPolynomial=0; SPI_Init(SPI5,&spi); SPI_Cmd(SPI5,ENABLE); } unsigned char spi_byte_read(unsigned char addr) { while (SPI_I2S_GetFlagStatus(SPI5, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI5,addr); while (SPI_I2S_GetFlagStatus(SPI5, SPI_I2S_FLAG_RXNE) == RESET); return SPI_I2S_ReceiveData(SPI5); } static int __init spi_init(void) { int ret; int i; int tem=0; unsigned int pclk1; uint8_t frequence; spi_cdev = cdev_alloc(); if(spi_cdev == NULL){ return -ENOMEM; } cdev_init(spi_cdev,&spi_ops); devno = MKDEV(major,minor); ret = register_chrdev_region(devno, count, DEVNAME); if(ret){ goto ERR_STEP; } ret = cdev_add(spi_cdev, devno, count); if(ret){ goto ERR_STEP1; } spi_config_init(); //Sm mode SystemCoreClockUpdate(); pclk1 = SystemCoreClock >> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE1)>> RCC_CFGR_PPRE1_Pos]; printk("---> SystemCoreClock=%d, pclk1=%d\n",SystemCoreClock, pclk1); frequence = pclk1/1000000; if(frequence > 42) { frequence = 42; } if(frequence < 2) { frequence = 2; } for(i=0;i<6;i++) { // spi[i].bus->CR2 = frequence; //the max frequence is 42MHZ, min frequence is 2MHZ // printk("---> spi%d ,bus:%#x, CR2:%d, frequence: %d\n", i,spi[i].bus, spi[i].bus->CR2, frequence); // spi[i].bus->CCR = (frequence<<1) & 0x0FFF; //100K, standard mode // spi[i].bus->TRISE = frequence + 1; // printk("---> CCR:%#x, TRISE:%#x\n",spi[i].bus->CCR, spi[i].bus->TRISE); } return 0; ERR_STEP1: unregister_chrdev_region(devno,count); ERR_STEP: cdev_del(spi_cdev); return ret; } static void __exit spi_exit(void) { unregister_chrdev_region(MKDEV(major,minor),count); cdev_del(spi_cdev); } module_init(spi_init); module_exit(spi_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("zhouchao"); MODULE_DESCRIPTION("this is spi module");