I2C 总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。通信原理是通过对SCL和SDA线高低电平时序的控制,来产生I2C总线协议所需要的信号进行数据的传递。在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。
I2C通信方式为半双工,只有一根SDA线,同一时间只可以单向通信,RS485也为半双工,SPI和UART为双工。
I2C 总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。通信原理是通过对SCL和SDA线高低电平时序的控制,来产生I2C总线协议所需要的信号进行数据的传递。在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。
I2C通信方式为半双工,只有一根SDA线,同一时间只可以单向通信,RS485也为半双工,SPI和UART为双工。
ARM big.LITTLE 系统的软件技术
Robin Randhawa,首席工程师,2013 年 4 月
简介
移动应用已经发生了显著变化,当今的消费者更多地将智能手机应用于大部分互联生活。其中既包括高性能任务,例如网络浏览、导航和游戏,也包括那些要求不太苛刻的“始终在线,始终连接”后台任务,例如语音呼叫、社交网络和电子邮件服务。因此,移动电话已经成为很多消费者必不可少的计算设备。同时,平板电脑等新型移动设备也在重新定义计算平台,以应对消费者的需求。这一趋势为消费者创造了全新的内容互动方式,将以往只可能在固定设备上实现的应用带到移动设备上。这才是真正的智能下一代计算。
摩尔定律将如何往下发展?人们过去预测集成电路上可容纳的晶体管数目每隔 18 个月会增加一倍,直至从数千个增加至数十亿个晶体管,但如果真正审视单个处理器,却会发现它的性能增长停滞不前,因为您可以在系统中消耗的电能已经达到峰值。
对于未来的任何一款处理器,散热必然会限制其速度的大幅提高。一旦达到器件的热障,器件会融化,如果是在移动电话上,设备会开始发热,让用户感到不适。除了物理散热问题之外,能效也会变得相当低。如果调节处理器实施,使其速度逐渐加快,则其能耗将呈指数级增长,而为了增加最后这一丁点的性能,却会导致成本大幅提升。过去,尺寸增大一倍也意味着速度提高一倍,但到了现在,尺寸增大一倍却只能将速度提高几个百分点,因此出于复杂性的原因,效益不复存在,这也是单核系统的速度达到极限的原因之一。
如果您无法让单核运行更快,则必须增加核心的数量。这样做的好处还包括让每个核心能够匹配其承担的工作负载,这正是 ARM big.LITTLE™ 处理概念的用武之地。
Big.LITTLE处理技术可以解决我们当前面临的一个最大难题:扩展消费者的“始终在线,始终连接”移动体验,同时改进性能,延长电池续航时间。实现这一目标的方式是将“big”多核处理器与“LITTLE”多核处理器配合使用,根据性能要求,为适当的任务无缝选择适当的处理器。重要的是,这种动态选择对在处理器上运行的应用程序软件或中间件是透明的。 设备中采用的最新一代big.LITTLE 设计将高性能Cortex™-A15 多处理器集群与高能效Cortex-A7 多处理器集群组合在一起。这些处理器保持了 100% 架构兼容性,并且具有相同的功能(支持 LPAE 和虚拟化扩展,以及 NEON™ 和 VFP 等功能单元),这使得针对一种处理器类型编译的软件应用程序能够在其他处理器上运行,而无需进行修改。
继续阅读白皮书:ARM big.LITTLE 系统的软件技术
常见无线通信概念简述
继续阅读常见无线通信概念简述
在开发Ti CC1310
应用的时候遇到了SDK
版本兼容问题。早期的应用都是从SDK 1.60
版本的例子中修改得来的,最近在升级到SDK 2.x
版本的时候遇到了编译不通过的问题。主要是某些变量名的定义改变了。
但是,翻遍了代码也没找打一个SDK
版本宏。
于是只能通过ti/devices/cc13x0/driverlib/driverlib_release.h
文件里面的DRIVERLIB_RELEASE_BUILD
的版本号来进行区分,根据数字的不同来使用不同的代码,例子如下:
#include <ti/devices/cc13x0/driverlib/driverlib_release.h> /*SDK 1_60_00_21*/ #if (DRIVERLIB_RELEASE_BUILD <= 50218) const DisplaySharp_HWAttrs displaySharpHWattrs = { .spiIndex = CC1310_LAUNCHXL_SPI0, .csPin = CC1310_LAUNCHXL_LCD_CS, .extcominPin = CC1310_LAUNCHXL_LCD_EXTCOMIN, .powerPin = CC1310_LAUNCHXL_LCD_POWER, .enablePin = CC1310_LAUNCHXL_LCD_ENABLE, .pixelWidth = BOARD_DISPLAY_SHARP_SIZE, .pixelHeight = BOARD_DISPLAY_SHARP_SIZE, .displayBuf = sharpDisplayBuf, }; #else /*SDK 2_10_02_10*/ const DisplaySharp_HWAttrsV1 displaySharpHWattrs = { .spiIndex = CC1310_LAUNCHXL_SPI0, .csPin = CC1310_LAUNCHXL_LCD_CS, .powerPin = CC1310_LAUNCHXL_LCD_POWER, .enablePin = CC1310_LAUNCHXL_LCD_ENABLE, .pixelWidth = BOARD_DISPLAY_SHARP_SIZE, .pixelHeight = BOARD_DISPLAY_SHARP_SIZE, .displayBuf = sharpDisplayBuf, }; #endif
/* * =============================== RF Driver =============================== */ #include <ti/drivers/rf/RF.h> /*SDK 1_60_00_21*/ #if (DRIVERLIB_RELEASE_BUILD <= 50218) const RFCC26XX_HWAttrs RFCC26XX_hwAttrs = { .hwiCpe0Priority = ~0, .hwiHwPriority = ~0, .swiCpe0Priority = 0, .swiHwPriority = 0, }; #else /*SDK 2_10_02_10*/ const RFCC26XX_HWAttrsV2 RFCC26XX_hwAttrs = { .hwiPriority = ~0, /* Lowest HWI priority */ .swiPriority = 0, /* Lowest SWI priority */ .xoscHfAlwaysNeeded = true, /* Keep XOSC dependency while in stanby */ .globalCallback = NULL, /* No board specific callback */ .globalEventMask = 0 /* No events subscribed to */ }; #endif
其他的就是动态链接库的位置不同,导致链接的时候报告找不到链接库,需要重新设置一下,或者简单的移除一些找不到的库即可,例子中并没有用到全部的链接库。
Code Composer Studio 8.2
提供的Runtime Object View (ROV)
是一个非常好用的功能,能动态监视系统的运行情况。
该功能需要使用TI-RTOS
的应用才可以正常使用。
下面是官方的参考文档:
继续阅读Code Composer Studio 8.2运行时对象查看器Runtime Object View (ROV)
我们在实际编写代码的时候,经常需要判断当前编译环境是否存在我们需要的头文件,如果不存在,则使用其他头文件代替。
以前这个操作都是通过外部的configure
文件生成Makefile
的时候指定。
最近的GCC
已经增加了__has_include
这个内置函数判断头文件是否存在。
这个功能最早是Clang
实现的,现在GCC
终于补上了这个功能。
例子如下:
#ifdef __has_include # if __has_include(<optional>) # include <optional> # define have_optional 1 # elif __has_include(<experimental/optional>) # include <experimental/optional> # define have_optional 1 # define experimental_optional # else # define have_optional 0 # endif #endif
Code Composer Studio 8.2.0.00007
,GCC 5
支持这个内置函数。
在使用Ti CC1310
的硬件I2C
与外部设备进行通信的时候,无法长时间稳定运行,尤其是平时的测试开发板,使用杜邦线连接的情况下。
同等情况下的SPI
总线,一般不会发生此类问题,因此怀疑是GPIO
管脚的驱动能力不足导致的。
我的工程是通过简单修改Ti CC1310 SDK
自带的Code Composer Studio
的例子工程而创建的,因此存在已经进行过默认配置的CC1310_LAUNCHXL.c
,CC1310_LAUNCHXL.h
这两个文件。用Code Composer Studio
完全重新创建的工程,缺乏必要的默认配置。因此,我们还是建议根据Ti CC1310 SDK
自带的例子进行修改,而不是完全从头创建工程。
我们研究I2C
初始化GPIO
管脚的代码在simplelink_cc13x0_sdk_2_30_00_20/source/ti/drivers/i2c/I2CCC26XX.c
,相关的代码如下:
/* * ======== I2CCC26XX_initIO ======== * This functions initializes the I2C IOs. * * @pre Function assumes that the I2C handle is pointing to a hardware * module which has already been opened. */ static int I2CCC26XX_initIO(I2C_Handle handle, void *pinCfg) { I2CCC26XX_Object *object; I2CCC26XX_HWAttrsV1 const *hwAttrs; I2CCC26XX_I2CPinCfg i2cPins; PIN_Config i2cPinTable[3]; uint32_t i=0; /* Get the pointer to the object and hwAttrs */ object = handle->object; hwAttrs = handle->hwAttrs; /* If the pinCfg pointer is NULL, use hwAttrs pins */ if (pinCfg == NULL) { i2cPins.pinSDA = hwAttrs->sdaPin; i2cPins.pinSCL = hwAttrs->sclPin; } else { i2cPins.pinSDA = ((I2CCC26XX_I2CPinCfg *)pinCfg)->pinSDA; i2cPins.pinSCL = ((I2CCC26XX_I2CPinCfg *)pinCfg)->pinSCL; } /* Handle error */ if(i2cPins.pinSDA == PIN_UNASSIGNED || i2cPins.pinSCL == PIN_UNASSIGNED) { return I2C_STATUS_ERROR; } /* Configure I2C pins SDA and SCL*/ i2cPinTable[i++] = i2cPins.pinSDA | PIN_INPUT_EN | PIN_PULLUP | PIN_OPENDRAIN; i2cPinTable[i++] = i2cPins.pinSCL | PIN_INPUT_EN | PIN_PULLUP | PIN_OPENDRAIN; i2cPinTable[i++] = PIN_TERMINATE; /* Allocate pins*/ object->hPin = PIN_open(&object->pinState, i2cPinTable); if (!object->hPin) { return I2C_STATUS_ERROR; } /* Set IO muxing for the UART pins */ PINCC26XX_setMux(object->hPin, i2cPins.pinSDA, IOC_PORT_MCU_I2C_MSSDA); PINCC26XX_setMux(object->hPin, i2cPins.pinSCL, IOC_PORT_MCU_I2C_MSSCL); return I2C_STATUS_SUCCESS; }
从上面的代码中,我们发现GPIO
管脚的驱动能力没有设置,根据CC13x0, CC26x0 SimpleLink ™ Wireless MCU Technical Reference Manual中的介绍,我们发现,如果不设置,默认情况下是PIN_DRVSTR_MIN(< (*) Lowest drive strength)
。这个驱动模式下,最省电,但是当有干扰存在的情况下,最容易导致出现错误。
查找Ti CC1310
提供的I2C
驱动程序,没有找到可以设置管脚驱动能力的接口。
网上有人通过直接修改Ti CC1310
提供的I2C
驱动程序,也就是simplelink_cc13x0_sdk_2_30_00_20/source/ti/drivers/i2c/I2CCC26XX.c
里的初始化代码(见上面的代码段)增加驱动能力属性来实现这个功能。
但是这种修改方式不推荐,修改的侵入太强。
从GPIO
的操作函数中,我们找到如下函数:
/** @brief Returns pin configuration * * @param pinId Pin ID * @return Current pin configuration as a device-independent #PIN_Config value * @note The pin ID is embedded in return value. * @note There is usually a device-specific version of this function that * returns device-specific options * @par Usage * @code * // Get config of pin 14 to be able to revert later * myPinConfig = PIN_getConfig(PIN_ID(14)); * // ... * // Lots of pin reconfigurations * // ... * // Restore previous configuration * PIN_setConfig(hPins, PIN_BM_ALL, myPinConfig); * @endcode */ extern PIN_Config PIN_getConfig(PIN_Id pinId); /** @brief Sets complete pin configuration * * @param handle Handle provided by previous call to PIN_open() * @param updateMask Bitmask specifying which fields in cfg that should take * effect, the rest keep their current value. * @param pinCfg #PIN_Config entry with pin ID and pin configuration * @return #PIN_SUCCESS if successful, else error code * @par Usage * @code * // Set drive strength on pin 15 * PIN_setConfig(hPins, PIN_BM_DRVSTR, PIN_ID(15)|PIN_DRVSTR_MAX); * @endcode */ extern PIN_Status PIN_setConfig(PIN_Handle handle, PIN_Config updateMask, PIN_Config pinCfg);
我们尝试从上层找到I2C
驱动使用的GPIO
管脚,然后调整其驱动能力。
/* I2C */ #define CC1310_LAUNCHXL_I2C0_SCL0 (IOID_5) #define CC1310_LAUNCHXL_I2C0_SDA0 (IOID_6)
/* * =============================== I2C =============================== */ #include <ti/drivers/I2C.h> #include <ti/drivers/i2c/I2CCC26XX.h> I2CCC26XX_Object i2cCC26xxObjects[CC1310_LAUNCHXL_I2CCOUNT]; const I2CCC26XX_HWAttrsV1 i2cCC26xxHWAttrs[CC1310_LAUNCHXL_I2CCOUNT] = { { .baseAddr = I2C0_BASE, .powerMngrId = PowerCC26XX_PERIPH_I2C0, .intNum = INT_I2C_IRQ, .intPriority = ~0, .swiPriority = 0, .sdaPin = CC1310_LAUNCHXL_I2C0_SDA0, .sclPin = CC1310_LAUNCHXL_I2C0_SCL0, } }; const I2C_Config I2C_config[CC1310_LAUNCHXL_I2CCOUNT] = { { .fxnTablePtr = &I2CCC26XX_fxnTable, .object = &i2cCC26xxObjects[CC1310_LAUNCHXL_I2C0], .hwAttrs = &i2cCC26xxHWAttrs[CC1310_LAUNCHXL_I2C0] } }; const uint_least8_t I2C_count = CC1310_LAUNCHXL_I2CCOUNT;
从上面我们看到I2C
句柄的.object
指针指向了I2CCC26XX_Object
类型的结构体,这个结构体在simplelink_cc13x0_sdk_2_30_00_20/source/ti/drivers/i2c/I2CCC26XX.c
里的static int I2CCC26XX_initIO(I2C_Handle handle, void *pinCfg)
函数中被初始化,这个结构体记录了详细的GPIO
操作句柄。
因此我们可以使用如下的代码对GPIO
管脚的驱动能力进行调整:
#include <ti/drivers/I2C.h> #include <ti/drivers/i2c/I2CCC26XX.h> #include "CC1310_LAUNCHXL.h" static I2C_Handle initI2c(void) { I2C_Params i2cParams; /* Create I2C for usage */ I2C_Params_init(&i2cParams); i2cParams.bitRate = I2C_400kHz; i2cParams.transferMode = I2C_MODE_BLOCKING; I2C_Handle i2c = I2C_open(Board_I2C_TMP, &i2cParams); if (NULL == i2c) { return NULL; } /* Change I2C Pin Drive Strength*/ /*CC1310_LAUNCHXL.c I2CCC26XX_Object i2cCC26xxObjects[CC1310_LAUNCHXL_I2CCOUNT];*/ I2CCC26XX_Object* i2cObj = i2c->object; if (NULL != i2cObj) { PIN_Config pinCfg = PIN_getConfig(PIN_ID(CC1310_LAUNCHXL_I2C0_SDA0)); PIN_Status status = PIN_setConfig(i2cObj->hPin, PIN_BM_ALL, pinCfg | PIN_DRVSTR_MAX); if (PIN_SUCCESS != status){ I2C_close(i2c); return NULL; } pinCfg = PIN_getConfig(PIN_ID(CC1310_LAUNCHXL_I2C0_SCL0)); status = PIN_setConfig(i2cObj->hPin, PIN_BM_ALL, pinCfg | PIN_DRVSTR_MAX); if (PIN_SUCCESS != status){ I2C_close(handle->i2c); return NULL; } } return i2c; }
最近在参照 树莓派实时系统下脚本语言的选择(应当使用Lua而不是Python) 调用调试lua-zmq
的时候,发现使用PAIR
模式进行线程之间通信,长时间运行后会出现死锁的情况。
当我们需要跟踪问题的时候,使用apt-get
安装的版本缺乏必要的调试信息。
我们可以手工安装调试信息包,如下:
$ sudo apt install libzmq-dbg # 系统默认的lua 5.1的符号信息使用如下命令安装 $ sudo apt-get install liblua5.1-0-dbg # libreadline提供了多个版本(5,6,7),根据需要下载对应的版本 $ sudo apt-get install libreadline6-dbg # sudo apt-get install search libtinfo* 根据返回的结果安装 $ sudo apt-get install libtinfo5-dbg
我们也可以从源代码重新编译一份,如下:
# 打开源代码的源 $ sudo sed -i "s/^#deb-src/deb-src/g" /etc/apt/sources.list # 安装必要的编译工具 $ sudo apt-get install build-essential devscripts lintian $ cd ~ # 下载源代码,此处不可sudo,否则后续操作会出现权限问题 $ apt-get source libzmq-dev $ cd zeromq*/ # 安装依赖项 $ sudo apt-get install libpgm-dev $ sudo apt-get install uuid-dev $ debuild -us -uc -b $ cd .. $ sudo dpkg -i libzmq-dev*.deb $ sudo dpkg -i libzmq-dbg*.deb $ sudo ldconfig
以上是针对Debian
安装包来进行的处理,然而对于luarocks
安装的插件来说,默认luarocks
是不能编译调试版本的,此时就需要我们手工编译了。我们以lua-zmq
为例子,参考如下:
$ sudo apt-get -y install cmake $ git clone git://github.com/Neopallium/lua-zmq.git $ git checkout v1.1 $ cd lua-zmq ; mkdir build ; cd build $ cmake -DCMAKE_BUILD_TYPE=Debug .. $ make $ sudo make install $ sudo ldconfig
USB
转串口设备,在Linux
下面都是免驱动的,但是到了macOS High Sierra(10.13.6)
上,无法正常识别。在Linux
上通过lsusb
可以看到如下信息:
Bus 001 Device 008: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
继续阅读macOS High Sierra(10.13.6)使用HL-340(CH340/CH341)芯片的USB转串口设备