#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "stm32f4xx.h" #include "stm32f4xx_hal_gpio.h" #include "stm32_hal_legacy.h" #include "driver.h" #define I2C_MAJOR MAJOR_I2C //static int minor = 0; //static dev_t devno; //static struct cdev *i2c_cdev = NULL; //static int count = 3; //static int ret=0; #define DEVNAME "i2c" #define NUM_OF_DEVICES 3 static uint8_t i2c_rcv_buf[100]; static uint8_t i2c_rcv_size; static DECLARE_WAIT_QUEUE_HEAD(wq); static volatile int ev_press = 0; struct i2c_device { dev_t devno; struct cdev cdev; char name[16]; IRQn_Type Event_IRQn; IRQn_Type Err_IRQn; } i2c_dev[NUM_OF_DEVICES]; static int i2c_open(struct inode *inode, struct file *filep); static int i2c_close(struct inode *inode, struct file *filep); static ssize_t i2c_read(struct file *filep, char __user *buf, size_t size, loff_t *offset); static ssize_t i2c_write(struct file *filep, const char __user *buf, size_t size, loff_t *offset); static int i2c_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); static struct file_operations i2c_ops = { .owner = THIS_MODULE, .open = i2c_open, .release = i2c_close, .ioctl = i2c_ioctl, .read = i2c_read, .write = i2c_write, }; static int i2c_open(struct inode *inode, struct file *filep) { int imajor,iminor; I2C_HandleTypeDef hi2c; imajor = MAJOR(inode->i_rdev); iminor = MINOR(inode->i_rdev); if(imajor != I2C_MAJOR) { printk("Error: %s %d i2c major fail! %d\n",__FILE__,__LINE__,imajor); return -1; } switch(iminor) { case 0: HAL_NVIC_EnableIRQ(I2C1_EV_IRQn); HAL_NVIC_EnableIRQ(I2C1_ER_IRQn); hi2c.Instance = I2C1; printk("i2c1 open\n"); break; case 1: HAL_NVIC_EnableIRQ(I2C2_EV_IRQn); HAL_NVIC_EnableIRQ(I2C2_ER_IRQn); hi2c.Instance = I2C2; printk("i2c2 open\n"); break; case 2: HAL_NVIC_EnableIRQ(I2C3_EV_IRQn); HAL_NVIC_EnableIRQ(I2C3_ER_IRQn); hi2c.Instance = I2C3; break; default: printk("Error:%s %d Invalid minor %d",__FILE__,__LINE__,iminor); return -1; } __HAL_I2C_DISABLE(&hi2c); //clear all flags. hi2c.State = HAL_I2C_STATE_READY; __HAL_I2C_ENABLE(&hi2c); //HAL_I2C_EnableListen_IT(&hi2c); return 0; } static int i2c_close(struct inode *inode, struct file *filep) { int imajor,iminor; I2C_HandleTypeDef hi2c; imajor = MAJOR(inode->i_rdev); iminor = MINOR(inode->i_rdev); if(imajor != I2C_MAJOR) { printk("Error: %s %d i2c major fail! %d\n",__FILE__,__LINE__,imajor); return -1; } switch(iminor) { case 0: HAL_NVIC_DisableIRQ(I2C1_EV_IRQn); HAL_NVIC_DisableIRQ(I2C1_ER_IRQn); hi2c.Instance = I2C1; printk("i2c1 close\n"); break; case 1: HAL_NVIC_DisableIRQ(I2C2_EV_IRQn); HAL_NVIC_DisableIRQ(I2C2_ER_IRQn); hi2c.Instance = I2C2; printk("i2c2 close\n"); break; case 2: HAL_NVIC_DisableIRQ(I2C3_EV_IRQn); HAL_NVIC_DisableIRQ(I2C3_ER_IRQn); hi2c.Instance = I2C3; break; default: printk("Error:%s %d Invalid minor %d",__FILE__,__LINE__,iminor); return -1; } __HAL_I2C_DISABLE(&hi2c); return 0; } irqreturn_t i2cErrIRQHandler(int irqno, void *dev_id) { I2C_HandleTypeDef hi2c; switch(irqno) { case I2C1_EV_IRQn: hi2c.Instance = I2C1; printk("i2c1 Error, restart...\n"); break; case I2C2_EV_IRQn: hi2c.Instance = I2C2; printk("i2c2 Error, restart...\n"); break; case I2C3_EV_IRQn: hi2c.Instance = I2C3; printk("i2c3 Error, restart...\n"); break; default: return IRQ_HANDLED; } //restart i2c hi2c.State = HAL_I2C_STATE_READY; __HAL_I2C_DISABLE(&hi2c); __HAL_I2C_ENABLE(&hi2c); return IRQ_HANDLED; } /** ** @brief This function handles I2C event interrupt request. ** @param ** @retval **/ irqreturn_t i2cEvIRQHandler(int irqno, void *dev_id) { I2C_HandleTypeDef hi2c; uint32_t sr2itflags; uint32_t sr1itflags; uint32_t itsources; uint32_t CurrentMode; // memcpy(h12c, &I2cHandle, sizeof(I2C_HandleTypeDef)); switch(irqno) { case I2C1_EV_IRQn: hi2c.Instance = I2C1; break; case I2C2_EV_IRQn: hi2c.Instance = I2C2; break; case I2C3_EV_IRQn: hi2c.Instance = I2C3; break; default: return IRQ_HANDLED; } hi2c.Mode = HAL_I2C_MODE_SLAVE; sr2itflags = READ_REG(hi2c.Instance->SR2); sr1itflags = READ_REG(hi2c.Instance->SR1); itsources = READ_REG(hi2c.Instance->CR2); CurrentMode = hi2c.Mode; // printk("SR1: %#x, SR2: %#x, CR2: %#x\n", sr1itflags, sr2itflags, itsources); /* Slave mode selected */ /* ADDR set --------------------------------------------------------------*/ if(((sr1itflags & I2C_FLAG_ADDR) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) { i2c_rcv_size = 0; /* Clear ADDR flag */ __HAL_I2C_CLEAR_ADDRFLAG(&hi2c); } else if(((sr1itflags & I2C_FLAG_RXNE) != RESET)) { i2c_rcv_buf[i2c_rcv_size++] = hi2c.Instance->DR; } /* STOPF set --------------------------------------------------------------*/ else if(((sr1itflags & I2C_FLAG_STOPF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) { ev_press = 1; wake_up_interruptible(&wq); /* Clear STOPF flag */ __HAL_I2C_CLEAR_STOPFLAG(&hi2c); } else { //clear all flags hi2c.State = HAL_I2C_STATE_READY; __HAL_I2C_DISABLE(&hi2c); __HAL_I2C_ENABLE(&hi2c); } return IRQ_HANDLED; } static int i2c_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) { uint32_t pclk1 = 0; I2C_HandleTypeDef I2CxHandle; i2c_arg_t i2c_arg; int imajor,iminor; HAL_StatusTypeDef retSta; IRQn_Type I2CxEvIRQn; imajor = MAJOR(inode->i_rdev); iminor = MINOR(inode->i_rdev); if(imajor != I2C_MAJOR) { printk("Error: %s %d i2c major fail! %d\n",__FILE__,__LINE__,imajor); return -EFAULT; } if ( copy_from_user(&i2c_arg, (void*)arg, sizeof(i2c_arg_t)) != 0) { printk("---> copy form user space fail!\n"); return -EFAULT; } if(iminor == 0) { I2CxHandle.Instance = I2C1; I2CxEvIRQn = I2C1_EV_IRQn; } else if(iminor == 1) { I2CxHandle.Instance = I2C2; I2CxEvIRQn = I2C2_EV_IRQn; } else if(iminor == 2) { I2CxHandle.Instance = I2C3; I2CxEvIRQn = I2C3_EV_IRQn; } else { printk(KERN_ERR"Invalid minor\n"); return -EFAULT; } switch(cmd) { case SET_I2C_SPEED: /* Get PCLK1 frequency */ pclk1 = HAL_RCC_GetPCLK1Freq(); __HAL_I2C_DISABLE(&I2CxHandle); HAL_NVIC_DisableIRQ(I2CxEvIRQn); if(i2c_arg.ClockSpeed <= 100000) I2CxHandle.Instance->CCR = I2C_SPEED_STANDARD(pclk1, i2c_arg.ClockSpeed) & 0x7fff; else I2CxHandle.Instance->CCR = I2C_SPEED_FAST(pclk1, i2c_arg.ClockSpeed, I2C_DUTYCYCLE_16_9) | 0x8000; __HAL_I2C_ENABLE(&I2CxHandle); HAL_NVIC_EnableIRQ(I2CxEvIRQn); //HAL_I2C_EnableListen_IT(&I2CxHandle); break; case GET_I2C_SPEED: pclk1 = HAL_RCC_GetPCLK1Freq(); if(I2CxHandle.Instance->CCR & 0x8000) //fast mode i2c_arg.ClockSpeed = pclk1/((I2CxHandle.Instance->CCR & I2C_CCR_CCR)*25); else //slow mode i2c_arg.ClockSpeed = pclk1/((I2CxHandle.Instance->CCR & I2C_CCR_CCR)<<1); if(copy_to_user((void*)arg, &i2c_arg, sizeof(i2c_arg_t))) return -EFAULT; break; case SET_I2C_ADDR: //8bit __HAL_I2C_DISABLE(&I2CxHandle); HAL_NVIC_DisableIRQ(I2CxEvIRQn); /* Configure I2Cx: Own Address1 and addressing mode */ I2CxHandle.Instance->OAR1 = (I2C_ADDRESSINGMODE_7BIT | i2c_arg.OwnAddress1)&0xff; __HAL_I2C_ENABLE(&I2CxHandle); HAL_NVIC_EnableIRQ(I2CxEvIRQn); //HAL_I2C_EnableListen_IT(&I2CxHandle); printk("OAR1: %#x\n", I2CxHandle.Instance->OAR1); break; case GET_I2C_ADDR: //8bit i2c_arg.OwnAddress1 = I2CxHandle.Instance->OAR1 & 0x0ff; if(copy_to_user((void*)arg, &i2c_arg, sizeof(i2c_arg_t))) return -EFAULT; break; case I2C_MASTER_TRANSFER: HAL_NVIC_DisableIRQ(I2CxEvIRQn); I2CxHandle.State = HAL_I2C_STATE_READY; I2CxHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; retSta = HAL_I2C_Master_Transmit(&I2CxHandle, (uint16_t)i2c_arg.DevAddress, i2c_arg.buf, i2c_arg.Size, 100); //timeout 1s if(retSta != HAL_OK) { printk(KERN_ERR"I2C master tansfer error, minor = %d, Err = %#x\n", iminor, retSta); } HAL_NVIC_EnableIRQ(I2CxEvIRQn); //HAL_I2C_EnableListen_IT(&I2CxHandle); break; case I2C_MASTER_RECEIVE: HAL_NVIC_DisableIRQ(I2CxEvIRQn); I2CxHandle.State = HAL_I2C_STATE_READY; I2CxHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; retSta = HAL_I2C_Master_Receive(&I2CxHandle, (uint16_t) i2c_arg.DevAddress, i2c_arg.buf, i2c_arg.Size, 100); //timeout 1s if(retSta != HAL_OK) { printk(KERN_ERR"I2C master recevice error!\n"); } if(copy_to_user((void*)arg, &i2c_arg, sizeof(i2c_arg_t))) return -EFAULT; HAL_NVIC_EnableIRQ(I2CxEvIRQn); //HAL_I2C_EnableListen_IT(&I2CxHandle); break; case I2C_SLAVE_RECEIVE_IT: I2CxHandle.State = HAL_I2C_STATE_READY; HAL_I2C_EnableListen_IT(&I2CxHandle); wait_event_interruptible(wq, ev_press); ev_press = 0; memcpy(i2c_arg.buf, i2c_rcv_buf, i2c_rcv_size); i2c_arg.Size = i2c_rcv_size; if(copy_to_user((void*)arg, &i2c_arg, sizeof(i2c_arg_t))) return -EFAULT; break; default: printk("---> Invalid action\n"); return -1; break; } return 0; } static ssize_t i2c_read(struct file *filep, char __user *buf, size_t size, loff_t *offset) { return 0; } static ssize_t i2c_write(struct file *filep, const char __user *buf, size_t size, loff_t *offset) { return 0; } void i2c_hw_init(void) { I2C_HandleTypeDef I2cHandle; GPIO_InitTypeDef GPIO_InitStruct; //enable periph clock __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_I2C1_CLK_ENABLE(); __HAL_RCC_I2C2_CLK_ENABLE(); __HAL_RCC_I2C3_CLK_ENABLE(); //config gpio GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; //I2C1 GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; //SCL | SDA GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); //I2C2 GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5; //SCL | SDA GPIO_InitStruct.Alternate = GPIO_AF4_I2C2; HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); //I2C3 GPIO_InitStruct.Alternate = GPIO_AF4_I2C3; GPIO_InitStruct.Pin = GPIO_PIN_8; //SCL HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_9; //SDA HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); //config I2C controller I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; I2cHandle.Init.ClockSpeed = 100000; I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_16_9; I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; I2cHandle.Init.OwnAddress1 = 0x40; //default address I2cHandle.Init.OwnAddress2 = 0xFE; I2cHandle.State = HAL_I2C_STATE_READY; I2cHandle.Instance = I2C1; if(HAL_I2C_Init(&I2cHandle) != HAL_OK) { printk(KERN_ERR"I2C1 hw init error!\n"); } HAL_NVIC_SetPriority(I2C1_EV_IRQn, 2, 0); HAL_NVIC_SetPriority(I2C1_ER_IRQn, 15, 0); //HAL_NVIC_EnableIRQ(I2C1_EV_IRQn); //HAL_I2C_EnableListen_IT(&I2cHandle); I2cHandle.Instance = I2C2; if(HAL_I2C_Init(&I2cHandle) != HAL_OK) { printk(KERN_ERR"I2C1 hw init error!\n"); } HAL_NVIC_SetPriority(I2C2_EV_IRQn, 2, 0); HAL_NVIC_SetPriority(I2C2_ER_IRQn, 15, 0); //HAL_NVIC_EnableIRQ(I2C2_EV_IRQn); //HAL_I2C_EnableListen_IT(&I2cHandle); I2cHandle.Instance = I2C3; if(HAL_I2C_Init(&I2cHandle) != HAL_OK) { printk(KERN_ERR"I2C1 hw init error!\n"); } HAL_NVIC_SetPriority(I2C3_EV_IRQn, 2, 0); HAL_NVIC_SetPriority(I2C3_ER_IRQn, 15, 0); //HAL_NVIC_EnableIRQ(I2C3_EV_IRQn); //HAL_I2C_EnableListen_IT(&I2cHandle); } static int __init i2c_init(void) { int ret; int i; for (i = 0; i < NUM_OF_DEVICES; i++) { printk("i2c%d module start...\n", i+1); i2c_dev[i].devno = MKDEV(MAJOR_I2C, i); sprintf(i2c_dev[i].name, "%s%d", DEVNAME, i+1); register_chrdev_region(i2c_dev[i].devno, 1, i2c_dev[i].name); cdev_add(&i2c_dev[i].cdev, i2c_dev[i].devno, 1); cdev_init(&i2c_dev[i].cdev, &i2c_ops); } i2c_hw_init(); i2c_dev[0].Event_IRQn = I2C1_EV_IRQn; i2c_dev[1].Event_IRQn = I2C2_EV_IRQn; i2c_dev[2].Event_IRQn = I2C3_EV_IRQn; i2c_dev[0].Err_IRQn = I2C1_ER_IRQn; i2c_dev[1].Err_IRQn = I2C2_ER_IRQn; i2c_dev[2].Err_IRQn = I2C3_ER_IRQn; for(i=0; i