Microchipharmony软件模拟I2C开发.docx

  1. 1、本文档共6页,可阅读全部内容。
  2. 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
Microchipharmony软件模拟I2C开发

Microchip 软I2C及线程间资源保护调试笔记关于I2C总线的特性:软I2C的SDA, SCL IO口要求设置为开漏/开集输出, 这种模式在IO口输出赋1时, IO口处于高阻态, 并不输出高电平, 高电平实际由上拉电路提供; 赋0时, IO口对地短路. 这种模式可实现总线电平与模式. 在I2C总线上有多个主设备时特别需要设置此模式, 另外在主从设备工作电压不一致时也需要设置此模式.主设备I2C速率需要根据从设备规格和主设备CPU时钟来调整延时.由于使用RTOS多线程系统, 要避免I2C操作被任务轮转和硬件中断打断, 造成读写失败. 通过挂起其他线程和关闭全局中断实现.由于从设备内部部分操作(例如EEPROM写入, CYPRESS内部校验运算)比较费时, 考虑到其他线程的及时性, 对主设备I2C的读/写代码/耗时应尽量短, 批量读写操作应尽量做分步.策略1) 需要延时等待的操作, 例如EEPROM写命令完成后需要等待内部写入完成, 这样的操作尽可能不要在写函数尾部增加等待代码, 要充分利用其他线程的运行来消化这部分等待时间. 因此在读/写函数开始时, 首先要增加问询从设备是否就绪的操作, 即重复对从设备发送START知道获取ACK.在新代码中, 关于I2C读写函数, 全部改成switch-case状态机结构, 一方面是方便程序复用, 不同类型从设备的读写函数基本上只要修改I2C_START分支中每次发送START是否问询失败后是否发送STOP, 和失败后的等待延时, 根据从设备规格书来确认. 以及从设备写地址长度(1字节/2字节/..)另一方面是方便代码阅读, 各个时序通过case分支分隔开, 容易与规格书比对.策略2) 批量操作分步进行, 以EEPROM的全片清除为例原有的批量清除代码如下, 由于Clear过程耗时非常长(大约7秒), 因此调用Clear的线程会在清除期间完全占用CPU, 造成其他线程无法处理任务, 因此需要增加vTaskDelay, 让线程每清完一个page时释放CPU. 同时由于vTaskDelay延时分辨率(及任务轮转频率), 延时时间相对比较长, 如代码中的实际延时为4ms, (轮转频率调高会造成更多的任务调度时间浪费, 即CPU时间浪费), 多次循环带来的延时占用也相当长, 按本例的EEPROM大小可造成2秒多的时间浪费.另外由于vTaskDelay的调用, eeprom_Clear函数必须在线程任务函数里面调用, 这个副作用无法显性的在代码中说明, 容易造成误用. 线程应该尽可能地遵循fast in fast out的原则, 以尽量保证各个同优先级线程间的平等性, 保证各线程能及时处理任务.策略: 将长任务通过状态机机制(如 switch-case)划分子阶段, 各case分支即子阶段代码的执行耗时应尽可能短.调整后的代码如下:通过一个static局部变量和返回状态, 实现三个目标:Clear函数每次只清除一个page函数重进, 通过返回值来确认全片清除完成函数不再调用vTaskDelay, 是函数本身的调用位置没有任务函数内外的局限对Clear函数的调用方式如下图:可以在while内部调用vTaskDelay达到释放CPU的效果, 有调用线程本身来决定延时.例子中没有调用vTaskDelay, 而是调用taskYIELD, 以下结合双线程测试说明.以下代码分属两个线程, 分别处理EEPROM和Cypress芯片, 两个芯片同时挂在I2C总线上, 需要考虑两个线程在使用I2C总线时的互斥.TEST0_Tasks: EEPROMTEST1_Tasks: Cypress以下是两个线程运行的log打印记录本例在EEPROM清除的循环中调用taskYIELD, taskYIELD的功能是使线程立即释放CPU并重新进入等待队列EEPROM的指令传输(一个page 6~9ms)和写入时间(max. 5ms)大概在11~14ms, TEST0_Task每完成一次page清除就通过taskYIELD释放CPU, 由于TEST1_Task的挂起延时为4ms, 所以两个线程单次任务交替进行, 从log可以看到实际情况如此.特别注意: 由于TEST1_Task的挂起延时4ms正好与EEPROM写入时间接近, 即一次线程轮转的过程所消耗的时间内可完成EEPROM写入, 所以可以使用taskYIELD, 否则仍然应该调用vTaskDelay给予足够的时延.下面的log是把taskYIELD注释掉执行的结果:很明显, TEST0_Task在清除完整片EEPROM之前, 完全占用CPU, 之后在其50ms的挂起延时中, TEST1_Task才获取CPU, 执行若干次之后CPU再次被TEST0_Task占用.

文档评论(0)

haihang2017 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档