|
@@ -37,8 +37,10 @@
|
|
|
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;
|
|
|
+static DECLARE_WAIT_QUEUE_HEAD(wq_1);
|
|
|
+static DECLARE_WAIT_QUEUE_HEAD(wq_2);
|
|
|
+static DECLARE_WAIT_QUEUE_HEAD(wq_3);
|
|
|
+static volatile int ev_press_1 = 0, ev_press_2 = 0, ev_press_3 = 0;
|
|
|
|
|
|
|
|
|
struct i2c_device {
|
|
@@ -171,6 +173,7 @@ irqreturn_t i2cErrIRQHandler(int irqno, void *dev_id)
|
|
|
printk("i2c3 Error, restart...\n");
|
|
|
break;
|
|
|
default:
|
|
|
+ printk("Unknow irqno! %#x\n", irqno);
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
@@ -194,6 +197,8 @@ irqreturn_t i2cEvIRQHandler(int irqno, void *dev_id)
|
|
|
uint32_t sr1itflags;
|
|
|
uint32_t itsources;
|
|
|
uint32_t CurrentMode;
|
|
|
+ wait_queue_head_t *pwq = NULL;
|
|
|
+ int *pev_press = NULL;
|
|
|
|
|
|
// memcpy(h12c, &I2cHandle, sizeof(I2C_HandleTypeDef));
|
|
|
|
|
@@ -201,12 +206,18 @@ irqreturn_t i2cEvIRQHandler(int irqno, void *dev_id)
|
|
|
{
|
|
|
case I2C1_EV_IRQn:
|
|
|
hi2c.Instance = I2C1;
|
|
|
+ pwq = &wq_1;
|
|
|
+ pev_press = &ev_press_1;
|
|
|
break;
|
|
|
case I2C2_EV_IRQn:
|
|
|
hi2c.Instance = I2C2;
|
|
|
+ pwq = &wq_2;
|
|
|
+ pev_press = &ev_press_2;
|
|
|
break;
|
|
|
case I2C3_EV_IRQn:
|
|
|
hi2c.Instance = I2C3;
|
|
|
+ pwq = &wq_3;
|
|
|
+ pev_press = &ev_press_3;
|
|
|
break;
|
|
|
default:
|
|
|
return IRQ_HANDLED;
|
|
@@ -218,7 +229,7 @@ irqreturn_t i2cEvIRQHandler(int irqno, void *dev_id)
|
|
|
itsources = READ_REG(hi2c.Instance->CR2);
|
|
|
CurrentMode = hi2c.Mode;
|
|
|
|
|
|
- // printk("SR1: %#x, SR2: %#x, CR2: %#x\n", sr1itflags, sr2itflags, itsources);
|
|
|
+ //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))
|
|
@@ -234,28 +245,27 @@ irqreturn_t i2cEvIRQHandler(int irqno, void *dev_id)
|
|
|
/* 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);
|
|
|
+
|
|
|
+ *pev_press = 1;
|
|
|
+ wake_up_interruptible(pwq);
|
|
|
+ //printk("irqno: %#x\n", irqno);
|
|
|
+
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//clear all flags
|
|
|
+ //printk("---> Unknow irq\n");
|
|
|
hi2c.State = HAL_I2C_STATE_READY;
|
|
|
- __HAL_I2C_DISABLE(&hi2c);
|
|
|
- __HAL_I2C_ENABLE(&hi2c);
|
|
|
+ //__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;
|
|
@@ -264,6 +274,8 @@ static int i2c_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
|
|
|
int imajor,iminor;
|
|
|
HAL_StatusTypeDef retSta;
|
|
|
IRQn_Type I2CxEvIRQn;
|
|
|
+ wait_queue_head_t *pwq = NULL;
|
|
|
+ int *pev_press = NULL;
|
|
|
|
|
|
imajor = MAJOR(inode->i_rdev);
|
|
|
iminor = MINOR(inode->i_rdev);
|
|
@@ -284,16 +296,22 @@ static int i2c_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
|
|
|
{
|
|
|
I2CxHandle.Instance = I2C1;
|
|
|
I2CxEvIRQn = I2C1_EV_IRQn;
|
|
|
+ pwq = &wq_1;
|
|
|
+ pev_press = &ev_press_1;
|
|
|
}
|
|
|
else if(iminor == 1)
|
|
|
{
|
|
|
I2CxHandle.Instance = I2C2;
|
|
|
I2CxEvIRQn = I2C2_EV_IRQn;
|
|
|
+ pwq = &wq_2;
|
|
|
+ pev_press = &ev_press_2;
|
|
|
}
|
|
|
else if(iminor == 2)
|
|
|
{
|
|
|
I2CxHandle.Instance = I2C3;
|
|
|
I2CxEvIRQn = I2C3_EV_IRQn;
|
|
|
+ pwq = &wq_3;
|
|
|
+ pev_press = &ev_press_3;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -307,7 +325,6 @@ static int i2c_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
|
|
|
/* 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;
|
|
@@ -315,8 +332,6 @@ static int i2c_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
|
|
|
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:
|
|
@@ -332,14 +347,11 @@ static int i2c_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
|
|
|
|
|
|
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;
|
|
|
|
|
@@ -350,9 +362,8 @@ static int i2c_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
|
|
|
break;
|
|
|
|
|
|
case I2C_MASTER_TRANSFER:
|
|
|
- HAL_NVIC_DisableIRQ(I2CxEvIRQn);
|
|
|
-
|
|
|
-
|
|
|
+ __HAL_I2C_DISABLE_IT(&I2CxHandle, I2C_IT_EVT | I2C_IT_ERR);
|
|
|
+
|
|
|
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
|
|
@@ -361,13 +372,11 @@ static int i2c_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
|
|
|
printk(KERN_ERR"I2C master tansfer error, minor = %d, Err = %#x\n", iminor, retSta);
|
|
|
}
|
|
|
|
|
|
- HAL_NVIC_EnableIRQ(I2CxEvIRQn);
|
|
|
- //HAL_I2C_EnableListen_IT(&I2CxHandle);
|
|
|
+ __HAL_I2C_ENABLE_IT(&I2CxHandle, I2C_IT_EVT | I2C_IT_ERR);
|
|
|
break;
|
|
|
|
|
|
case I2C_MASTER_RECEIVE:
|
|
|
- HAL_NVIC_DisableIRQ(I2CxEvIRQn);
|
|
|
-
|
|
|
+ __HAL_I2C_DISABLE_IT(&I2CxHandle, I2C_IT_EVT | I2C_IT_ERR);
|
|
|
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
|
|
@@ -378,17 +387,25 @@ static int i2c_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
|
|
|
if(copy_to_user((void*)arg, &i2c_arg, sizeof(i2c_arg_t)))
|
|
|
return -EFAULT;
|
|
|
|
|
|
- HAL_NVIC_EnableIRQ(I2CxEvIRQn);
|
|
|
- //HAL_I2C_EnableListen_IT(&I2CxHandle);
|
|
|
+ __HAL_I2C_ENABLE_IT(&I2CxHandle, I2C_IT_EVT | I2C_IT_ERR);
|
|
|
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(0 == wait_event_interruptible_timeout(*pwq, *pev_press, 3*HZ)) //3s
|
|
|
+ {
|
|
|
+ i2c_arg.Size = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ *pev_press = 0;
|
|
|
+ memcpy(i2c_arg.buf, i2c_rcv_buf, i2c_rcv_size);
|
|
|
+ i2c_arg.Size = i2c_rcv_size;
|
|
|
+ }
|
|
|
+
|
|
|
+ //printk("SR1: %#x, SR2: %#x, CR1: %#x, CR2: %#x\n", I2CxHandle.Instance->SR1,
|
|
|
+ // I2CxHandle.Instance->SR2, I2CxHandle.Instance->CR1, I2CxHandle.Instance->CR2);
|
|
|
|
|
|
if(copy_to_user((void*)arg, &i2c_arg, sizeof(i2c_arg_t)))
|
|
|
return -EFAULT;
|
|
@@ -450,12 +467,12 @@ void i2c_hw_init(void)
|
|
|
|
|
|
//config I2C controller
|
|
|
I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
|
|
- I2cHandle.Init.ClockSpeed = 200000;
|
|
|
+ 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.OwnAddress1 = 0x22; //default address
|
|
|
I2cHandle.Init.OwnAddress2 = 0xFE;
|
|
|
I2cHandle.State = HAL_I2C_STATE_READY;
|
|
|
|