查看: 6483|回复: 5

[求助] imx6ul I2C总线驱动通道2功能不正常

[复制链接]

该用户从未签到

2

主题

5

帖子

0

新手上路

Rank: 1

积分
28
最后登录
2017-6-22
发表于 2017-3-17 16:23:28 | 显示全部楼层 |阅读模式
本帖最后由 诸葛一帆丶 于 2017-3-21 10:42 编辑

最近要用到I2C总线,发现以下问题:

使用的IMX6ULEVK 28616


写的I2C总线驱动,测试过能使用I2C通道1正常收发,使用I2C通道2时无法正常通信(整个驱动程序并没有进行修改)
通过读取寄存器数据发现,在写入从设备地址至I2Cx_I2DR这步中,I2C通道1能正常写入(读取到的值和写入的值相同),I2C通道2无法正常写入(读取到的值为0)。

(寄存器查过地址没问题,都是基址加偏移,1通道基址0x021A0000,2通道基址0x021A4000


I2C1读取到的寄存器:
I2Cx_I2CR寄存器值为0xb0,
I2Cx_I2SR寄存器值为0xa3,
I2Cx_IFDR寄存器值为0x39,
I2Cx_I2DR寄存器值为0x1a

I2C2读取到的寄存器:
I2Cx_I2CR寄存器值为0xb0,
I2Cx_I2SR寄存器值为0x81,
I2Cx_IFDR寄存器值为0x39,
I2Cx_I2DR寄存器值为0


现在猜测是不是I2C2总线是不是有问题?
或者在驱动程序的哪部分会出现问题呢?
求助

0317-1.png

0通道能正常传输,能进中断,1通道无法进中断,(应该是发送从机地址不成功,所以进不了中断)



0321-1.png 0321-2.png 0321-3.png

I2C通道1,从机地址为0x0E,寄存器地址0x07
I2C通道2,从机地址为0x1A,寄存器地址0x00








  1. /*********************************************************************************************************
  2. ** 函数名称: __imx6ulI2cStart
  3. ** 功能描述: i2c 控制器发送启动字节
  4. ** 输 入  : usAddr     地址
  5. **           usFlag     标志
  6. **           uiChannel  通道号
  7. ** 输 出  : NONE
  8. ** 全局变量:
  9. ** 调用模块:
  10. *********************************************************************************************************/
  11. static VOID  __imx6ulI2cStart (UINT16  usAddr,
  12.                                UINT16  usFlag,
  13.                                UINT    uiChannel)
  14. {
  15.     bspDebugMsg(" __imx6ulI2cStart\r\n");
  16.     UINT    uiValue;

  17.     __Gi2cChannel[uiChannel].iStatus = __I2C_BUS_STATE_START;           /*  启动总线                    */

  18.     switch(uiChannel) {
  19. #if 1
  20.     case I2C_CHAN_1:
  21.         API_InterVectorEnable(IMX_INT_I2C1);                            /*  启动总线中断                */
  22.         break;

  23.     case I2C_CHAN_2:
  24.         API_InterVectorEnable(IMX_INT_I2C2);                            /*  启动总线中断                */
  25.         break;

  26.     case I2C_CHAN_3:
  27.         API_InterVectorEnable(IMX_INT_I2C3);                            /*  启动总线中断                */
  28.         break;

  29.     case I2C_CHAN_4:
  30.         API_InterVectorEnable(IMX_INT_I2C4);                            /*  启动总线中断                */
  31.         break;
  32. #endif
  33.     default:
  34.         break;
  35.     }

  36.     uiValue  =  readw(REG_I2C_I2CR(uiChannel));                         /*  使能I2C中断                 */
  37.     uiValue |=  BIT_I2C_I2CR_IIEN;
  38.     writew(uiValue, REG_I2C_I2CR(uiChannel));


  39.     if (usFlag & LW_I2C_M_RD) {                                         /*  读操作                      */
  40.         uiValue  =  readw(REG_I2C_I2CR(uiChannel));                     /*  重启总线 需要有此操作       */
  41.         uiValue |=  BIT_I2C_I2CR_RSTA;
  42.         writew(uiValue, REG_I2C_I2CR(uiChannel));

  43.         writew(((usAddr << 1) | I2C_READ), (REG_I2C_I2DR(uiChannel)));  /*  设置器件读地址              */
  44.     } else {

  45.         uiValue  =  readw(REG_I2C_I2CR(uiChannel));                     /*  主发模式启动                */
  46.         uiValue |=  (BIT_I2C_I2CR_MSTA | BIT_I2C_I2CR_MTX);
  47.         writew(uiValue, REG_I2C_I2CR(uiChannel));

  48.         {
  49.         writew(((usAddr << 1) | I2C_WRITE), (REG_I2C_I2DR(uiChannel))); /*  设置器件写地址              */

  50.         printk("%d    pChar = %#x\n", __LINE__, ((usAddr << 1) | I2C_WRITE));
  51.         printk("%d    uiChannel = %d REG_I2C_I2DR = %#x\n", __LINE__, uiChannel, readw(REG_I2C_I2DR(uiChannel)));
  52.         }
  53.     }
  54. }

  55. /*********************************************************************************************************
  56. ** 函数名称: __imx6ulI2cStop
  57. ** 功能描述: i2c 控制器发送停止总线
  58. ** 输 入  : uiChannel  通道号
  59. ** 输 出  : NONE
  60. ** 全局变量:
  61. ** 调用模块:
  62. *********************************************************************************************************/
  63. static VOID  __imx6ulI2cStop (UINT uiChannel)
  64. {
  65.     bspDebugMsg(" __imx6ulI2cStop\r\n");
  66.     UINT    uiValue;

  67.     uiValue  = readw(REG_I2C_I2CR(uiChannel));                          /*  主收模式停止                */
  68.     uiValue &= ~(BIT_I2C_I2CR_MSTA);
  69.     writew(uiValue, REG_I2C_I2CR(uiChannel));

  70.     __Gi2cChannel[uiChannel].iStatus = __I2C_BUS_STATE_STOP;            /*  停止总线                    */

  71.     API_SemaphoreBPost(__Gi2cChannel[uiChannel].I2C_hSignal);           /*  激活等待任务                */
  72. }

  73. /*********************************************************************************************************
  74. ** 函数名称:
  75. ** 功能描述: i2c 控制器中断处理函数
  76. ** 输 入  : pI2cChannel     通道号
  77. ** 输 出  : LW_IRQ_HANDLED  系统中断返回值
  78. ** 全局变量: NONE
  79. ** 调用模块: NONE
  80. ********************************************************************************************************/
  81. static irqreturn_t  __i2cIsr (UINT   uiI2cChannel)
  82. {
  83.     bspDebugMsg(" __i2cIsr\r\n");
  84.     BYTE     ucByte;
  85.     ULONG    ulStatus;
  86.     UINT     uiValue;
  87.     __PI2C_CHANNEL  pI2cChannel = &__Gi2cChannel[uiI2cChannel];

  88.     ulStatus  =  readw(REG_I2C_I2SR(pI2cChannel->uiChannel));           /*  i2c 状态                    */
  89.     ulStatus &= ~BIT_I2C_I2SR_IIF;
  90.     writew(ulStatus, REG_I2C_I2SR(pI2cChannel->uiChannel));             /*  清中断                      */

  91.     uiValue = readw(REG_I2C_I2SR(pI2cChannel->uiChannel));
  92.     if ((uiValue & BIT_I2C_I2SR_IAL) > 0) {
  93.                                                                         /*  中断仲裁                    */
  94.         errno = ENXIO;
  95.         __imx6ulI2cStop(pI2cChannel->uiChannel);                        /*  停止总线                    */
  96.     }

  97.     switch (pI2cChannel->iStatus) {                                     /*  处理不同状态                */

  98.     case __I2C_BUS_STATE_IDLE:
  99.         break;                                                          /*  直接退出                    */

  100.     case __I2C_BUS_STATE_START:
  101.         if ((__I2C_BUS_IS_LASTMSG(pI2cChannel) &&                       /*  没有待处理的消息            */
  102.             (pI2cChannel->pi2cmsg->I2CMSG_usLen == 0))) {
  103.             errno = ENXIO;
  104.             __imx6ulI2cStop(pI2cChannel->uiChannel);                    /*  停止总线                    */
  105.             break;
  106.           }
  107.         if (pI2cChannel->pi2cmsg->I2CMSG_usFlag & LW_I2C_M_RD) {        /*  进入读状态                  */
  108.             pI2cChannel->iStatus = __I2C_BUS_STATE_READ;
  109.             uiValue  =  readw(REG_I2C_I2CR(pI2cChannel->uiChannel));     /*  主收模式启动                */
  110.             uiValue &= ~BIT_I2C_I2CR_MTX;
  111.             writew(uiValue, REG_I2C_I2CR(pI2cChannel->uiChannel));
  112.             if (pI2cChannel->pi2cmsg->I2CMSG_usLen == 1) {               /*  若为最后一个消息,不发送ACK */
  113.             uiValue  =  readw(REG_I2C_I2CR(pI2cChannel->uiChannel));
  114.             uiValue |=  BIT_I2C_I2CR_TXAK;
  115.             writew(uiValue, REG_I2C_I2CR(pI2cChannel->uiChannel));
  116.             }
  117.            readw(REG_I2C_I2DR(pI2cChannel->uiChannel));                 /*  dummy read 空读             */
  118.         } else {
  119.             pI2cChannel->iStatus = __I2C_BUS_STATE_WRITE;               /*  进入写状态                  */
  120.             goto    __prepare_write;
  121.         }
  122.         break;

  123.     case __I2C_BUS_STATE_READ:
  124.         if (__I2C_BUS_IS_MSGEND(pI2cChannel)) {                         /*  当前为最后一个字节          */
  125.             if (__I2C_BUS_IS_LASTMSG(pI2cChannel)) {                    /*  这是最后一个消息块          */
  126.                 pI2cChannel->iMsgPtr = 0;
  127.                 pI2cChannel->iMsgIndex++;                               /*  保证与消息数量相同          */
  128.                 __imx6ulI2cStop(pI2cChannel->uiChannel);
  129.                 break;
  130.             } else {
  131.                 pI2cChannel->iMsgPtr = 0;
  132.                 pI2cChannel->iMsgIndex++;
  133.                 pI2cChannel->pi2cmsg++;                                 /*  开始接收下一个消息          */
  134.             }
  135.         } else if (__I2C_BUS_IS_MSGLAST(pI2cChannel)) {                 /*  当前为倒数第二字节          */
  136.             if (__I2C_BUS_IS_LASTMSG(pI2cChannel)) {                    /*  这是最后一个消息块          */
  137.                 uiValue  =  readw(REG_I2C_I2CR(pI2cChannel->uiChannel));
  138.                 uiValue |=  BIT_I2C_I2CR_TXAK;
  139.                 writew(uiValue, REG_I2C_I2CR(pI2cChannel->uiChannel));  /*  下一个字节不发送ACK         */
  140.             }
  141.         }
  142.         ucByte = (BYTE)readw(REG_I2C_I2DR(pI2cChannel->uiChannel));     /*  读取数据                    */
  143.         pI2cChannel->pi2cmsg->I2CMSG_pucBuffer[pI2cChannel->iMsgPtr] = ucByte;
  144.         pI2cChannel->iMsgPtr++;
  145.         break;

  146.     case __I2C_BUS_STATE_WRITE:
  147.         if ((ulStatus & BIT_I2C_I2SR_RXAK) &&                           /*  需要 ACK 但没有接收到 ACK   */
  148.            !(pI2cChannel->pi2cmsg->I2CMSG_usFlag &
  149.              LW_I2C_M_IGNORE_NAK)) {
  150.             errno = ECONNREFUSED;
  151.             __imx6ulI2cStop(pI2cChannel->uiChannel);                    /*  停止总线                    */
  152.             break;
  153.         }

  154. __prepare_write:
  155.         if (!__I2C_BUS_IS_MSGEND(pI2cChannel)) {                        /*  当前消息还没有发送完        */
  156.             ucByte = pI2cChannel->pi2cmsg->I2CMSG_pucBuffer[pI2cChannel->iMsgPtr];
  157.             pI2cChannel->iMsgPtr++;
  158.             writew((ucByte), (REG_I2C_I2DR(pI2cChannel->uiChannel)));
  159.         } else if (!__I2C_BUS_IS_LASTMSG(pI2cChannel)) {                /*  还有剩余的消息没有发送完    */
  160.             pI2cChannel->iMsgPtr = 0;
  161.             pI2cChannel->iMsgIndex++;
  162.             pI2cChannel->pi2cmsg++;                                     /*  开始发送下一个消息          */
  163.             if (pI2cChannel->pi2cmsg->I2CMSG_usFlag &
  164.                 LW_I2C_M_NOSTART) {                                     /*  不需要起始位                */
  165.                 if (pI2cChannel->pi2cmsg->I2CMSG_usFlag &
  166.                     LW_I2C_M_RD) {                                      /*  读操作                      */

  167.                     /*
  168.                      *  控制器换向, 必须重启总线
  169.                      */
  170.                     __imx6ulI2cStop(pI2cChannel->uiChannel);            /*  不能进行读操作              */
  171.                 }
  172.                 goto    __prepare_write;
  173.             } else {
  174.                 __imx6ulI2cStart(pI2cChannel->pi2cmsg->I2CMSG_usAddr,
  175.                                  pI2cChannel->pi2cmsg->I2CMSG_usFlag,
  176.                                  pI2cChannel->uiChannel);               /*  重启总线                    */
  177.             }
  178.         } else {
  179.             pI2cChannel->iMsgPtr = 0;
  180.             pI2cChannel->iMsgIndex++;                                   /*  保证与消息数量相同          */
  181.             __imx6ulI2cStop(pI2cChannel->uiChannel);                    /*  发送结束                    */
  182.         }
  183.         break;

  184.     case __I2C_BUS_STATE_STOP:
  185.         break;

  186.     default:
  187.         break;
  188.         }

  189.     return  (LW_IRQ_HANDLED);
  190. }

  191. /*********************************************************************************************************
  192. ** 函数名称: __i2cTryTransfer
  193. ** 功能描述: i2c 尝试传输函数
  194. ** 输 入  : uiChannel    i2c 通道
  195. **           pI2cAdapter  i2c 适配器
  196. **           pI2cMsg      i2c 传输消息组
  197. **           iNum         消息数量
  198. ** 输 出  : 完成传输的消息数量
  199. ** 全局变量:
  200. ** 调用模块:
  201. *********************************************************************************************************/
  202. static INT  __i2cTryTransfer (UINT             uiChannel,
  203.                               PLW_I2C_ADAPTER  pI2cAdapter,
  204.                               PLW_I2C_MESSAGE  pI2cMsg,
  205.                               INT              iNum)
  206. {
  207.     bspDebugMsg(" __i2cTryTransfer\r\n");
  208.     __Gi2cChannel[uiChannel].iStatus    = __I2C_BUS_STATE_START;
  209.     __Gi2cChannel[uiChannel].iBpsParam  = SPECIFIED_RATE;
  210.     __Gi2cChannel[uiChannel].pi2cmsg    = pI2cMsg;
  211.     __Gi2cChannel[uiChannel].iMsgPtr    = 0;
  212.     __Gi2cChannel[uiChannel].iMsgNum    = iNum;
  213.     __Gi2cChannel[uiChannel].iMsgIndex  = 0;                            /*  从第一个开始发送            */

  214.     __imx6ulI2cStart(pI2cMsg->I2CMSG_usAddr,
  215.                      pI2cMsg->I2CMSG_usFlag,
  216.                      uiChannel);                                        /*  启动总线                    */

  217.     API_SemaphoreBPend(__Gi2cChannel[uiChannel].I2C_hSignal,
  218.                        LW_OPTION_WAIT_A_SECOND * 3);                    /*  最多等待 3 秒钟             */

  219.     switch(uiChannel) {

  220.     case I2C_CHAN_1:
  221.         API_InterVectorDisable(IMX_INT_I2C1);                           /*  关闭总线中断                */
  222.         break;

  223.     case I2C_CHAN_2:
  224.         API_InterVectorDisable(IMX_INT_I2C2);                           /*  关闭总线中断                */
  225.         break;

  226.     case I2C_CHAN_3:
  227.         API_InterVectorDisable(IMX_INT_I2C3);                           /*  关闭总线中断                */
  228.         break;

  229.     case I2C_CHAN_4:
  230.         API_InterVectorDisable(IMX_INT_I2C4);                           /*  关闭总线中断                */
  231.         break;

  232.     default:
  233.         break;
  234.     }

  235.     return  (__Gi2cChannel[uiChannel].iMsgIndex);                       /*  返回传输成功的数量          */
  236. }

  237. /*********************************************************************************************************
  238. ** 函数名称: __i2cTransfer
  239. ** 功能描述: i2c 传输函数
  240. ** 输 入  : uiChannel    i2c 通道
  241. **           pI2cAdapter  i2c 适配器
  242. **           pI2cMsg      i2c 传输消息组
  243. **           iNum         消息数量
  244. ** 输 出  : ERROR_CODE
  245. ** 全局变量:
  246. ** 调用模块:
  247. *********************************************************************************************************/
  248. static INT  __i2cTransfer (UINT             uiChannel,
  249.                            PLW_I2C_ADAPTER  pI2cAdapter,
  250.                            PLW_I2C_MESSAGE  pI2cMsg,
  251.                            INT              iNum)
  252. {
  253.     bspDebugMsg(" __i2cTransfer\r\n");
  254.     INT  i;

  255.     for (i = 0; i < pI2cAdapter->I2CADAPTER_iRetry; i++) {              /*  错误重传                   */
  256.         if (__i2cTryTransfer(uiChannel, pI2cAdapter, pI2cMsg, iNum) == iNum) {
  257.             return  (iNum);
  258.         } else {
  259.             API_TimeSleep(LW_OPTION_WAIT_A_TICK);                       /*  等待一个机器周期重试        */
  260.         }
  261.     }

  262.     return  (PX_ERROR);
  263. }

  264. /*********************************************************************************************************
  265. ** 函数名称: __i2c1Transfer
  266. ** 功能描述: i2c1 传输函数
  267. ** 输 入  : pI2cAdapter  i2c 适配器
  268. **           pI2cMsg      i2c 传输消息组
  269. **           iNum         消息数量
  270. ** 输 出  : i2c 传输函数
  271. ** 全局变量:
  272. ** 调用模块:
  273. *********************************************************************************************************/
  274. static INT  __i2c1Transfer (PLW_I2C_ADAPTER  pI2cAdapter,               /*  抽象成Transfer              */
  275.                             PLW_I2C_MESSAGE  pI2cMsg,
  276.                             INT              iNum)
  277. {
  278.     return  (__i2cTransfer(I2C_CHAN_1,
  279.                            pI2cAdapter,
  280.                            pI2cMsg,
  281.                            iNum));
  282. }

  283. /*********************************************************************************************************
  284. ** 函数名称: __i2c2Transfer
  285. ** 功能描述: i2c2 传输函数
  286. ** 输 入  : pI2cAdapter  i2c 适配器
  287. **           pI2cMsg      i2c 传输消息组
  288. **           iNum         消息数量
  289. ** 输 出  : i2c 传输函数
  290. ** 全局变量:
  291. ** 调用模块:
  292. *********************************************************************************************************/
  293. static INT  __i2c2Transfer (PLW_I2C_ADAPTER  pI2cAdapter,               /*  抽象成Transfer              */
  294.                             PLW_I2C_MESSAGE  pI2cMsg,
  295.                             INT              iNum)
  296. {
  297.     return  (__i2cTransfer(I2C_CHAN_2,
  298.                            pI2cAdapter,
  299.                            pI2cMsg,
  300.                            iNum));
  301. }

  302. /*********************************************************************************************************
  303. ** 函数名称: __i2c3Transfer
  304. ** 功能描述: i2c3 传输函数
  305. ** 输 入  : pI2cAdapter  i2c 适配器
  306. **           pI2cMsg      i2c 传输消息组
  307. **           iNum         消息数量
  308. ** 输 出  : i2c 传输函数
  309. ** 全局变量:
  310. ** 调用模块:
  311. *********************************************************************************************************/
  312. static INT  __i2c3Transfer (PLW_I2C_ADAPTER  pI2cAdapter,               /*  抽象成Transfer              */
  313.                             PLW_I2C_MESSAGE  pI2cMsg,
  314.                             INT              iNum)
  315. {
  316.     return  (__i2cTransfer(I2C_CHAN_3,
  317.                            pI2cAdapter,
  318.                            pI2cMsg,
  319.                            iNum));
  320. }

  321. /*********************************************************************************************************
  322. ** 函数名称: __i2c4Transfer
  323. ** 功能描述: i2c4 传输函数
  324. ** 输 入  : pI2cAdapter  i2c 适配器
  325. **           pI2cMsg      i2c 传输消息组
  326. **           iNum         消息数量
  327. ** 输 出  : i2c 传输函数
  328. ** 全局变量:
  329. ** 调用模块:
  330. *********************************************************************************************************/
  331. static INT  __i2c4Transfer (PLW_I2C_ADAPTER  pI2cAdapter,               /*  抽象成Transfer              */
  332.                             PLW_I2C_MESSAGE  pI2cMsg,
  333.                             INT              iNum)
  334. {
  335.     return  (__i2cTransfer(I2C_CHAN_4,
  336.                            pI2cAdapter,
  337.                            pI2cMsg,
  338.                            iNum));
  339. }

  340. /*********************************************************************************************************
  341.   i2c 驱动程序(操作函数集)
  342. *********************************************************************************************************/
  343. static LW_I2C_FUNCS  __Gimx6ulI2cFuncs[I2C_CHAN_NUM] = {
  344.         {
  345.                 __i2c1Transfer,                                         /*  I2C1传输函数                */
  346.         }, {
  347.                 __i2c2Transfer,
  348.         }, {
  349.                 __i2c3Transfer,
  350.         }, {
  351.                 __i2c4Transfer,
  352.         }
  353. };

  354. /*********************************************************************************************************
  355. ** 函数名称: __i2cSetI2cClk
  356. ** 功能描述: 设置时钟频率
  357. ** 输 入  : uiChannel  i2c 通道号
  358. **           uiBaud     时钟频率参数
  359. ** 输 出  : NONE
  360. ** 全局变量:
  361. ** 调用模块:
  362. *********************************************************************************************************/
  363. static VOID  __i2cSetI2cClk (UINT  uiChannel, UINT32  uiBaud)
  364. {
  365.     /*
  366.      *  获取系统时钟
  367.      */
  368. //    UINT32 uiSrcClk = ccmMainClkGet(IPG_PER_CLK);
  369.     UINT32 uiSrcClk   = 75 * 1000 * 1000;
  370.     UINT32 uiDivider  = uiSrcClk / uiBaud;
  371.     UINT8  ucIndex    = 0;
  372.     UINT   uiValue    = 0;

  373.     /*
  374.      *  波特率处理后与数组中对应值匹配,将对应值写入分频寄存器
  375.      */
  376.     if (uiDivider < __GusI2cClkDiv[0][0]) {
  377.         uiDivider = __GusI2cClkDiv[0][0];
  378.         ucIndex   = 0;
  379.         printk("Warning :can't find a smaller divider than %d.\n",
  380.                 uiDivider);
  381.         printk("SCL frequency is set at %d - expected was %d.\n",
  382.                 uiSrcClk / uiDivider, uiBaud);

  383.     } else if (uiDivider > __GusI2cClkDiv[49][0]) {
  384.         uiDivider = __GusI2cClkDiv[49][0];
  385.         ucIndex   = 49;
  386.         printk("Warning: can't find a bigger divider than %d.\n",
  387.                 uiDivider);
  388.         printk("SCL frequency is set at %d - expected was %d.\n",
  389.                 uiSrcClk / uiDivider, uiBaud);

  390.     } else {
  391.         for (ucIndex = 0; __GusI2cClkDiv[ucIndex][0] < uiDivider; ucIndex++);
  392.         uiDivider = __GusI2cClkDiv[ucIndex][0];
  393.     }

  394.     /*
  395.      *  设置I2C时钟频率
  396.      */
  397.     uiValue  =  readw(REG_I2C_IFDR(uiChannel));
  398.     uiValue &= ~BIT_I2C_IFDR_IC_MASK;
  399.     uiValue |=  __GusI2cClkDiv[ucIndex][1];
  400.     writew(uiValue, REG_I2C_IFDR(uiChannel));
  401. }

  402. /*********************************************************************************************************
  403. ** 函数名称: __i2cHwInit
  404. ** 功能描述:  i2c 控制器初始化
  405. ** 输 入  : uiChannel  i2c 通道
  406. ** 输 出  : ERROR_CODE
  407. ** 全局变量:
  408. ** 调用模块:
  409. *********************************************************************************************************/
  410. static INT  __i2cHwInit (UINT  uiChannel)
  411. {
  412.     UINT uiValue = 0;

  413.     __i2cSetI2cClk(uiChannel, I2C_BUS_FREQ_MAX);                        /*  设置时钟频率               */

  414.     /*
  415.      *  当作为从设备时,设备地址需自己设置
  416.      */
  417.     uiValue  =  readw(REG_I2C_IADR(uiChannel));                         /*  指定从设备地址             */
  418.     uiValue &= ~IMXUL_DEFAULT_SLAVE_ID_MASK;
  419.     uiValue |=  IMXUL_DEFAULT_SLAVE_ID;
  420.     writew(uiValue, REG_I2C_IADR(uiChannel));

  421.     writew(0, REG_I2C_I2SR(uiChannel));                                 /*  清零状态寄存器             */

  422.     uiValue  =  readw(REG_I2C_I2CR(uiChannel));                         /*  使能I2C                    */
  423.     uiValue |=  BIT_I2C_I2CR_IEN;
  424.     writew(uiValue, REG_I2C_I2CR(uiChannel));

  425.     return  (ERROR_NONE);
  426. }

  427. /*********************************************************************************************************
  428. ** 函数名称: __i2cInit
  429. ** 功能描述: 初始化 i2c 通道
  430. ** 输 入  : pI2cChannel  i2c 通道
  431. ** 输 出  : ERROR_CODE
  432. ** 全局变量:
  433. ** 调用模块:
  434. *********************************************************************************************************/
  435. static INT  __i2cInit (UINT  uiChannel)
  436. {
  437.     __PI2C_CHANNEL  pI2cChannel = &__Gi2cChannel[uiChannel];

  438.     if (!pI2cChannel->I2C_bIsInit) {                                    /*  判断通道是否已初始化          */
  439.        /*
  440.         * 初始化 I2C 使用的信号量
  441.         */
  442.        pI2cChannel->I2C_hSignal = API_SemaphoreBCreate("i2c_signal",
  443.                                              LW_FALSE,
  444.                                              LW_OPTION_OBJECT_GLOBAL,
  445.                                              LW_NULL);
  446.        if (pI2cChannel->I2C_hSignal == LW_OBJECT_HANDLE_INVALID) {
  447.            printk(KERN_ERR "imx6qI2cInit(): failed to create i2c_signal!\n");
  448.            goto  __error_handle;
  449.        }

  450.         /*
  451.          *  初始化 I2C 控制器
  452.          */
  453.         if (__i2cHwInit(pI2cChannel->uiChannel) != ERROR_NONE) {
  454.             printk(KERN_ERR "imx6ulI2cInit(): failed to init!\n");
  455.             goto  __error_handle;
  456.         }

  457.         switch(pI2cChannel->uiChannel) {

  458.         case I2C_CHAN_1:
  459.             API_InterVectorConnect(IMX_INT_I2C1,
  460.                                    (PINT_SVR_ROUTINE)__i2cIsr,
  461.                                    (PVOID)uiChannel,
  462.                                    "i2c1_isr");
  463.             break;

  464.         case I2C_CHAN_2:
  465.             API_InterVectorConnect(IMX_INT_I2C2,
  466.                                    (PINT_SVR_ROUTINE)__i2cIsr,
  467.                                    (PVOID)uiChannel,
  468.                                    "i2c2_isr");
  469.             break;

  470.         case I2C_CHAN_3:
  471.             API_InterVectorConnect(IMX_INT_I2C3,
  472.                                    (PINT_SVR_ROUTINE)__i2cIsr,
  473.                                    (PVOID)uiChannel,
  474.                                    "i2c3_isr");
  475.             break;

  476.         case I2C_CHAN_4:
  477.             API_InterVectorConnect(IMX_INT_I2C4,
  478.                                    (PINT_SVR_ROUTINE)__i2cIsr,
  479.                                    (PVOID)uiChannel,
  480.                                    "i2c4_isr");
  481.             break;

  482.         default:
  483.             printk(KERN_ERR "__i2cInit(): I2C channel invalid!\n");
  484.             break;
  485.         }

  486.         pI2cChannel->I2C_bIsInit = LW_TRUE;                             /*  设置已初始化标志              */
  487.     }

  488.     return  (ERROR_NONE);

  489. __error_handle:

  490.     if (pI2cChannel->I2C_hSignal) {
  491.         API_SemaphoreBDelete(&pI2cChannel->I2C_hSignal);
  492.         pI2cChannel->I2C_hSignal = 0;
  493.     }

  494.     return  (PX_ERROR);
  495. }

  496. /*********************************************************************************************************
  497. ** 函数名称: i2cIomuxConfig
  498. ** 功能描述: i2c管脚复用
  499. ** 输 入  : uiChannel  通道号
  500. ** 输 出  : NONE
  501. ** 全局变量: NONE
  502. ** 调用模块: NONE
  503. ********************************************************************************************************/
  504. static VOID  __i2cIomuxConfig (UINT  uiChannel)
  505. {
  506.     switch (uiChannel) {

  507.     case I2C_CHAN_1:                                                    /*  i2c1的管脚复用              */
  508.        IomuxConfig(__I2C1_SCL_REG,
  509.                    __I2C1_SCL_MASK,
  510.                    __I2C1_SCL_VAL);
  511.        IomuxConfig(__I2C1_SDA_REG,
  512.                    __I2C1_SDA_MASK,
  513.                    __I2C1_SDA_VAL);
  514.        break;

  515.     case I2C_CHAN_2:                                                     /*  i2c2的管脚复用              */
  516.         IomuxConfig(__I2C2_SCL_REG,
  517.                     __I2C2_SCL_MASK,
  518.                     __I2C2_SCL_VAL);
  519.         IomuxConfig(__I2C2_SDA_REG,
  520.                     __I2C2_SDA_MASK,
  521.                     __I2C2_SDA_VAL);
  522.         break;

  523.     case I2C_CHAN_3:                                                    /*  i2c3的管脚复用              */
  524.         IomuxConfig(__I2C3_SCL_REG,
  525.                     __I2C3_SCL_MASK,
  526.                     __I2C3_SCL_VAL);
  527.         IomuxConfig(__I2C3_SDA_REG,
  528.                     __I2C3_SDA_MASK,
  529.                     __I2C3_SDA_VAL);
  530.         break;

  531.     case I2C_CHAN_4:                                                    /*  i2c4的管脚复用              */
  532.         IomuxConfig(__I2C4_SCL_REG,
  533.                     __I2C4_SCL_MASK,
  534.                     __I2C4_SCL_VAL);
  535.         IomuxConfig(__I2C4_SDA_REG,
  536.                     __I2C4_SDA_MASK,
  537.                     __I2C4_SDA_VAL);
  538.         break;

  539.     default:
  540.         printk(KERN_ERR "i2cBusFuns(): I2C channel invalid!\n");
  541.     }

  542.     return;
  543. }

  544. /*********************************************************************************************************
  545. ** 函数名称: i2cBusFuns
  546. ** 功能描述: 初始化 i2c 总线并获取操作函数集
  547. ** 输 入  : uiChannel  通道号
  548. ** 输 出  : 总线操作函数集
  549. ** 全局变量:
  550. ** 调用模块:
  551. *********************************************************************************************************/
  552. PLW_I2C_FUNCS  i2cBusFuns (UINT  uiChannel)
  553. {
  554.     /*
  555.      *  设置芯片管脚分配,SylixOS 计数从零开始,而 IMX6UL 手册是从 1 开始,需要注意
  556.      */
  557.     __i2cIomuxConfig(uiChannel);

  558.     if (__i2cInit(uiChannel) != ERROR_NONE) {                           /*  初始化控制器              */
  559.         return  (LW_NULL);
  560.     }

  561.     return  (&__Gimx6ulI2cFuncs[uiChannel]);                            /*  返回操作函数集            */
  562. }

  563. /*********************************************************************************************************
  564. ** 函数名称: i2cBusCreate
  565. ** 功能描述: 初始化目标电路板i2c总线系统
  566. ** 输 入  : NONE
  567. ** 输 出  : NONE
  568. ** 全局变量:
  569. ** 调用模块:
  570. *********************************************************************************************************/
  571. VOID i2cBusCreate (VOID)
  572. {
  573.     /*
  574.      *  具体配置在common中
  575.      */
  576.     PLW_I2C_FUNCS    pI2cFuncs;

  577.     API_I2cLibInit();                                                   /*  初始化 i2c 组件库           */

  578. #if  CONFIG_BSP_I2C0
  579.     pI2cFuncs = i2cBusFuns(0);                                          /*  创建 i2c0总线适配器         */
  580.     if (pI2cFuncs) {
  581.         API_I2cAdapterCreate("/bus/i2c/0", pI2cFuncs, 10, 1);           /*  0 对应 I2C0                 */
  582.     }
  583. #endif
  584. #if  CONFIG_BSP_I2C1
  585.     pI2cFuncs = i2cBusFuns(1);                                          /*  创建 i2c1总线适配器         */
  586.     if (pI2cFuncs) {
  587.         API_I2cAdapterCreate("/bus/i2c/1", pI2cFuncs, 10, 1);           /*  1 对应 I2C1                 */
  588.     }
  589. #endif
  590. #if  CONFIG_BSP_I2C2
  591.     pI2cFuncs = i2cBusFuns(2);                                          /*  创建 i2c2总线适配器         */
  592.     if (pI2cFuncs) {
  593.         API_I2cAdapterCreate("/bus/i2c/2", pI2cFuncs, 10, 1);           /*  2 对应 I2C2                 */
  594.     }
  595. #endif
  596. #if  CONFIG_BSP_I2C3
  597.     pI2cFuncs = i2cBusFuns(3);                                          /*  创建 i2c3总线适配器         */
  598.     if (pI2cFuncs) {
  599.         API_I2cAdapterCreate("/bus/i2c/3", pI2cFuncs, 10, 1);           /*  3 对应 I2C3                 */
  600.     }
  601. #endif
  602. }

  603. /*********************************************************************************************************
  604. ** 函数名称: i2cBusDelete
  605. ** 功能描述: 卸载目标电路板i2c总线系统
  606. ** 输 入  : NONE
  607. ** 输 出  : NONE
  608. ** 全局变量:
  609. ** 调用模块:
  610. *********************************************************************************************************/
  611. VOID i2cBusDelete (VOID)
  612. {
  613. #if  CONFIG_BSP_I2C0
  614.     API_I2cAdapterDelete("/bus/i2c/0");                                 /*  0 对应 I2C0                 */
  615. #endif
  616. #if  CONFIG_BSP_I2C1
  617.     API_I2cAdapterDelete("/bus/i2c/1");                                 /*  1 对应 I2C1                 */
  618. #endif
  619. #if  CONFIG_BSP_I2C2
  620.     API_I2cAdapterDelete("/bus/i2c/2");                                 /*  2 对应 I2C2                 */
  621. #endif
  622. #if  CONFIG_BSP_I2C3
  623.     API_I2cAdapterDelete("/bus/i2c/3");                                 /*  3 对应 I2C3                 */
  624. #endif
  625. }

  626. /*********************************************************************************************************
  627. ** 函数名称: module_init
  628. ** 功能描述: module_init()驱动加载模块
  629. ** 输 入  : NONE
  630. ** 输 出  : NONE
  631. ** 全局变量:
  632. ** 调用模块:
  633. *********************************************************************************************************/
  634. VOID module_init (VOID)
  635. {
  636.     printf("hello_module init!\n");
  637.     i2cBusCreate();

  638.     UINT8 ucBuf;
  639.     UINT8 ucReg = 0x07;

  640.     LW_I2C_MESSAGE  i2cMsgs[2] = {
  641.         {
  642.             .I2CMSG_usAddr    = 0x0E,
  643.             .I2CMSG_usFlag    = 0,
  644.             .I2CMSG_usLen     = 1,
  645.             .I2CMSG_pucBuffer = &ucReg,
  646.         }, {
  647.             .I2CMSG_usAddr    = 0x0E,
  648.             .I2CMSG_usFlag    = LW_I2C_M_RD,
  649.             .I2CMSG_usLen     = 2,
  650.             .I2CMSG_pucBuffer = &ucBuf,
  651.         }
  652.     };

  653.     __i2cTryTransfer(1,LW_NULL,i2cMsgs,2);

  654.     printf("%d\n",ucBuf);
  655. }
复制代码






我知道答案 目前已有5人回答
0320-4.png
0320-5.png
0320-6.png
0320-7.png
回复

使用道具 举报

  • TA的每日心情
    难过
    2019-11-15 11:44
  • 签到天数: 117 天

    连续签到: 1 天

    [LV.6]常住居民II

    4

    主题

    362

    帖子

    0

    高级会员

    Rank: 4

    积分
    758
    最后登录
    2019-11-15
    发表于 2017-3-19 21:56:53 | 显示全部楼层
    你裸机?没有用操作系统?
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    2

    主题

    5

    帖子

    0

    新手上路

    Rank: 1

    积分
    28
    最后登录
    2017-6-22
     楼主| 发表于 2017-3-20 14:34:43 | 显示全部楼层
    风之狼 发表于 2017-3-19 21:56
    你裸机?没有用操作系统?

    有操作系统的
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    难过
    2019-11-15 11:44
  • 签到天数: 117 天

    连续签到: 1 天

    [LV.6]常住居民II

    4

    主题

    362

    帖子

    0

    高级会员

    Rank: 4

    积分
    758
    最后登录
    2019-11-15
    发表于 2017-3-20 18:20:42 | 显示全部楼层

    有没有可能操作系统已经占用了i2c2了?
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    2

    主题

    5

    帖子

    0

    新手上路

    Rank: 1

    积分
    28
    最后登录
    2017-6-22
     楼主| 发表于 2017-3-21 10:40:10 | 显示全部楼层
    风之狼 发表于 2017-3-20 18:20
    有没有可能操作系统已经占用了i2c2了?

    我用的是动态加载的方式,加载I2C模块,应该不会
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    难过
    2019-11-15 11:44
  • 签到天数: 117 天

    连续签到: 1 天

    [LV.6]常住居民II

    4

    主题

    362

    帖子

    0

    高级会员

    Rank: 4

    积分
    758
    最后登录
    2019-11-15
    发表于 2017-3-22 16:05:38 | 显示全部楼层
    诸葛一帆丶 发表于 2017-3-21 10:40
    我用的是动态加载的方式,加载I2C模块,应该不会

    你看看设备树有没有描述i2c2。我就是因为看到你动态加载才说的。
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-20 16:12 , Processed in 0.100332 second(s), 27 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表