Changes from v2.7.7 to v2.7.8:
[feat]:upgrade patch tool to v3.8 [opt]:opt code generate process display [opt]:opt login logic [opt]:opt ghs support [opt]:add MC03 ghs supportae455856-9c93-4b7f-8810-b5a8bbd6a1c7-image.png
将 SCL 对地短路后 Debug 查看 I2C 寄存器,MSTS -> BUSY 位置 1,I2c_MasterHwStatePtr = I2C_CHN_BUSY_STATUS。065b8965-524f-4213-b792-5e0d178ac1bb-image.png
I2C 发送 API CddI2c_SyncModeTransfer 函数里会判断 I2c 状态,此时 TempChannelStatus = I2C_CHN_ERROR_PRESENT 的情况下 API 是不会调用底层发送,所以 SCL 对地短路恢复后,I2C 总线通讯依旧无法恢复。bd6e1fae-6a40-4279-9308-63f6c49d95c2-image.png
2.1.1 排查方向一 推测是 I2C TOCFG Register 对 SCL 和 SDA 的常低检测导致的 SCL 对地短路恢复后总线通讯失败。但 TOCFG -> SDA 位为 0 的时候只检测 SCL 低电平超时时间,TOCFG -> SCL 位为 1 的时候检测 SCL 和 SDA 低电平超时时间,因此 SCL 低电平超时检测是无法关闭的ae41bf8d-ee9f-4927-98f3-d28b9f3928d7-image.png
在 I2C_Lld_MasterConfig 函数里将 I2C_Lld_MasterFeatureConfig 注释掉后,TOCFG -> SDA 位就不会被置 1,SDA 的低电平超时将不会被打开,此时使用逻辑分析仪抓取 I2C 设备的失联恢复的波形60fdd1ee-8b6d-49f6-9738-b4590b8b8dba-image.png
将 SDA 对地短路后进行测试。SDA 对地短路后 SDA 电平呈现常低,SCL 电平呈现常高,松开 SDA 对地短路后 SCL/SDA 电平均为常高,但 I2C 总线通讯失败,此时 SDA 常低检测处于未打开的情况,所以可以排除低电平超时导致的 I2C 总线发送失败的推断243b7060-38c5-4440-809b-ce9d8ea37e8e-image.png
2.1.2 排查方向二 推测是总线死锁导致的 SCL 对地短路恢复后总线通讯失败。参考 SDK 总线死锁的解决方案“https://forum.ytmicro.com/topic/603/i2c%E6%80%BB%E7%BA%BF%E6%AD%BB%E9%94%81%E9%97%AE%E9%A2%98%E4%BB%8B%E7%BB%8D”943959a4-8371-4b4f-a1e4-d6f367d98502-image.png
按照死锁的方式处理,SCL 对地短路恢复后,MCU 将 SCL配置为 GPIO,并输出 9 个 CLK 信号。实际测试也无法回复 I2C 总线通讯。 3. 解决方案 方案一: 检测 I2C 状态为 I2C_CHN_ERROR_PRESENT 的情况下,先反初始化 I2C 后,再重新初始化 I2C 即可恢复efd0d3dd-3ad2-43e1-bc0b-5afe70d7c8e2-image.png
方案二: CDDI2C MCAL 配置里 I2cBusIdleTimeout 配置是超时的配置,默认是 0(不开启),但当前版本测试开启后不生效。当前驱动没有检查这种情况的一个处理,后续 MCAL 版本更新后会修复88c1d22c-5a8b-4f02-a759-380049a8adb7-image.png
3a4a6966-d46a-478d-962e-483d51af2aba-image.png
对 PTD4 的 IO 反转操作只在中断回调函 I2C_SLAVE_EVENT_STOP Case 里操作4eecfcb4-3268-489c-b593-83364142c0e0-image.png
2. 问题分析 根据 I2C 驱动可以确认 I2C_SLAVE_EVENT_STOP 有三种条件会进入:① 重复接收起始位; ② 收到到错误 ;③ 总线上有 stop bit。也确认客户 restart 指令属于 重复接收起使位(repeat start ) 2.1 重复接收起始位 I2C_DRV_SlaveIRQHandler 函数中 repeatStartDetect 就是对 重复接收起始位 情况的判断。当 repeatStartDetect 置 1,会执行 I2C_DRV_SlaveEndTransferHandler 函数,然后通过回调函数进入 I2C_SLAVE_EVENT_STOP Case642f4da7-2bed-45cc-a3df-70f6b6f7a83a-image.png
6baa01ba-aae4-476e-8140-7dd5b467bae0-image.png
2.2 收到到错误 I2C_DRV_SlaveIRQHandler 函数中会判断 BitError 和 FIFOError。当 I2C 从机出现错误的情况下会执行 I2C_DRV_SlaveEndTransferHandler 函数,然后通过回调函数进入 I2C_SLAVE_EVENT_STOP Case5dbae1b4-3f09-45bf-a233-8af26c301a8e-image.png
2.3 总线上有 stop bit I2C_DRV_SlaveIRQHandler 函数中 stopDetect 就是对 总线上有 stop bit 情况的判断。当 stopDetect 置 1,会执行 I2C_DRV_SlaveEndTransferHandler 函数,然后通过回调函数进入 I2C_SLAVE_EVENT_STOP Case0ed833cd-cca7-45c8-94b8-2cc167162aaa-image.png
3. 解决方案 3.1 Plan A 如果不需要使用 重复接收起始位 进 I2C_SLAVE_EVENT_STOP,并且 I2C 不是使用 DMA,并且使能了监听的情况下,可以直接把 I2C_DRV_SlaveIRQHandler 函数里 repeatStartDetect 的 I2C_DRV_SlaveEndTransferHandler 函数直接注释即可66ffd82f-a1b2-460c-bc53-86a759950397-image.png
关于 I2C 产生 error 也进入 I2C_SLAVE_EVENT_STOP,可以在回调函数 I2C_SLAVE_EVENT_STOP Case 里调用 I2C_DRV_SlaveGetTransferStatus 函数获取 i2c 状态,如果产生 error 函数的返回值是 STATUS_ERROR,因此可以通过返回值去判断是否发产生 error6f2c71f9-2cfa-41cc-903b-9b3e83494c2c-image.png
注意事项: 此方案对 SDK I2C 驱动修改程度最小 此方案会导致主机发送主机写并且不发停止位情况下,无法获取主机写命令什么时候接收完成 3.2 Plan B 在 I2C_DRV_SlaveIRQHandler 函数里调用 I2C_DRV_SlaveEndTransferHandler 函数的位置加 log92ea1753-181c-4b3c-bf95-8fc343c93fef-image.png
然后在回调函数 I2C_SLAVE_EVENT_STOP case 里去判断对应的 log,然后做相应的处理0784d907-3432-4663-952b-19180284adff-image.png
注意事项: 此方案对 SDK I2C 驱动修改程度较大9ee02551-35ae-4b04-9bba-81aa137f1b7a-image.png
时钟为 8M,LOW 值为 0xFFF,根据公式计算,(4096 * 256)* (1 / 8M) = 131ms,而实际拉低时间是 800ms,确实触发超时,MSTS -> TOIF 标志位置 1,理论与实践现象一致。375c9480-42ca-4ca5-91f6-b53a79ea1109-image.png
2.2 HardFault 原因分析 使用 I2c_Master_Demo 例程,模仿客户代码调用方式对问题进行复现1039cc8a-d408-45fd-ae82-0f45fba727b3-image.png
实际 Debug 确定可以看到,当出现 HardFault 时,I2C 未接收完成6efa2f84-3a91-463d-b83e-072daf4ae7d9-image.png
1c1d7221-a043-49f3-b655-ac9467f5b130-image.png
当更改 RXBUFF 为静态局部变量后,就不会出现 HardFault ,其 I2C 通讯波形是完整的,有起始位和停止位。0692b417-fdf7-40f1-b3e2-b9ee7fae7f2c-image.png
3e2712aa-bfb1-41e7-bbde-6d5e7037e0cb-image.png
出现 HardFault 后观察栈空间以及修改栈空间大小均无效果,可以推断堆栈未出现溢出。RXBUFF 数组仅修改变量存储位置,即可避免 HardFault 出现,推测跟变量的存储位置及生命周期有关系,由于局部变量在函数执行结束后就释放了,可能是 i2c_Read 函数已经执行结束了,将 RXBUFF 数组释放了,但由于 I2C 接收还未完成,但接收 BUFF 已经被释放了,但此时还在给 RXBUFF 收数据,所以触发了 HardFault 。 在 i2c_Read 函数里和函数执行完成后分别设一个标志位,当出现 HardFault 的情况时 asd[1] 已经置 1 了,此时 i2c_Read 函数执行完毕 RXBUFF 数组已经被释放了,但此时 I2C 通讯还未结束,还在给 FIFO 写数据,所以触发了 HardFault 。614f878d-7414-44e1-9f1a-c6217d339793-image.png
3. 问题总结 使用 I2C_DRV_MasterReceiveData 函数时,必须使用 I2C_DRV_MasterGetTransferStatus 获取 I2C 状态,同时记得 I2C_DRV_MasterGetTransferStatus + while 等待的时候记得加上超时机制。9187f2f8-2da6-43e5-ae5b-a780d563a5d0-image.png
也可以将 RXBUFF 设置为全局变量或静态变量。I2c_Slave_Demo.zip 硬件:MD14 EVB or 客户板子 问题表述: I2C 从机模式时,客户想在回调函数里做处理,但不清楚回调函数里 Case 的使用情况。 2. Case 说明 I2C0_SlaveRxCpltCallback 函数 /* 伪 C 语言代码,直接编译会报错 */ void I2C0_SlaveRxCpltCallback(i2c_slave_event_t event, void *userData) { /* Get the instance number from userData */ uint32_t instance = 0; (void)userData; /* Depending on the event received, set the buffers or abort the transfer */ switch (event) { case I2C_SLAVE_EVENT_RX_REQ: /* * If the bus master requests data, then set the destination RX buffer * and accepted transfer size */ I2C_DRV_SlaveSetRxBuffer(instance, slaveRxBuffer, BUFF_SIZE); break; case I2C_SLAVE_EVENT_TX_REQ: /* * If the bus master sends data, then set the source TX buffer * and accepted transfer size */ I2C_DRV_SlaveSetTxBuffer(instance, slaveTxBuffer, BUFF_SIZE); break; case I2C_SLAVE_EVENT_TX_EMPTY: /* * If the TX buffer is empty. Because the example does not handle * this case there is no action taken. */ case I2C_SLAVE_EVENT_RX_FULL: /* * If the RX buffer is full, check the slave receive buffer is correct */ break; case I2C_SLAVE_EVENT_STOP: /* * This case is used when a stop condition is on the bus. Because * the example does not handle this case there is no action taken. */ break; } }
0b7d3fa6-05ae-4356-8070-568980a9a476-image.png
3. 获取接收 Data 的个数 使用 I2C_DRV_SlaveGetTransferStatus 函数可以获取 Data 接收的个数,I2C_DRV_SlaveSetTxBuffer 函数的第三个参数是当前 rxSize 的剩余长度,接收长度(已知) - bytesRemaining 得到当前接收了多少字节9dfa6e82-5e74-4d8f-8b15-13ddddb62ded-image.png
一、背景:
使用MCAL开发,版本为2.3.0
目前SPI配置为一个Sequence里面有一个Job,一个Job里面有两个Channel
调用顺序为先调用Spi_SetupEB再Spi_SyncTransmit
二、问题点:
①一个Job下配置了两个Channel ,在发送的时候片选信号未持续拉低
69022cf2-5c81-4eaa-8a64-28ad4ff7ee99-f86bbafeb72020994888d59a8261902d.png
②SPI channel的默认值,只有第一个字节生效(发送数据指针为空),并且Channel实际是要发送8个字节
0994ad48-a7ff-4b93-8ecb-0638ae30b9ff-4dddab3168dfc71bc9c6e20afdbdb278.png
针对上面两个问题,是YCT上哪些配置设置的不对导致的吗?该怎么修改或者有其他建议呀? 谢谢答疑
问题现象描述:
1.我配置ADC的一组为: 通道 0,1,12,13;当我读取ADC->FIFO时,有缺少的还有重复的channel-ID;
2.使用库函数读取ADC->FIFO时,存放寄存器变量的uint32 regValue的值 与寄存器视图 的值 不一致;
260ea2b5-f576-41cc-bf73-bfe4d0496c46-image.png
19c3b12a-ea72-4958-bca9-48a62739efbd-image.png
下面是我ADC的工具配置信息:
9d72f96a-fcb4-4acd-9c46-75eca83ac482-image.png
411a28e4-f1cb-44a5-9d89-ecb820500d49-image.png
d29bfdeb-d0ad-4dad-8c89-424c46896588-image.png
/* adc_config0 */ const adc_converter_config_t adc_config0={ .clockDivider=0, .startTime=12, .sampleTime=2, .overrunMode=false, .autoOffEnable=false, .waitEnable=false, .trigger=ADC_TRIGGER_SOFTWARE, .align=ADC_ALIGN_RIGHT, .resolution=ADC_RESOLUTION_12BIT, .dmaWaterMark=0, .dmaEnable=false, .sequenceConfig={ .sequenceMode=ADC_CONV_LOOP, .sequenceIntEnable=false, .convIntEnable=false, .readyIntEnable=false, .ovrunIntEnable=false, .sampIntEnable=false, .channels={ ADC_INPUTCHAN_EXT0, ADC_INPUTCHAN_EXT1, ADC_INPUTCHAN_EXT12, ADC_INPUTCHAN_EXT13, }, .totalChannels=4, }, .compareConfig={ .compareEnable=false, .compareAllChannelEnable=false, .compHigh=4095, .compLow=0, .compIntEnable=false, }, }; #define ADC_INST 0U adc_converter_config_t get_adc_config0; uint8_t set_adc_sequence_cnt = 2; uint8_t get_adc_sequence_cnt = 2; void ADC_Init(void) { ADC_DRV_ConfigConverter(ADC_INST,&adc_config0); ADC_DRV_Start(ADC_INST); //get adc sequence length set_adc_sequence_cnt = adc_config0.sequenceConfig.totalChannels; ADC_DRV_GetConverterConfig(ADC_INST, &get_adc_config0); get_adc_sequence_cnt = get_adc_config0.sequenceConfig.totalChannels; } void ADC_Get_Value_10ms(void) { uint32 reg_value = 0; for (uint8_t i = 0; i < set_adc_sequence_cnt; i++) { reg_value = ADC_DRV_ReadSeqtagAndData(ADC_INST); // uint8_t channel_id = reg_value>>16; uint8_t channel_id = (reg_value>>16)&0x1f; uint16_t chan_raw_data = (reg_value&0x0000ffff); if(channel_id == 0)//ADC0_SE0 { uint16 ADC_mV_IntPackVolt = 0; ADC_mV_IntPackVolt = (reg_value&0x0000ffff)*3300/4096; //test code to view the convert result of ADC ADC_mV_IntPackVolt = 1100; } } ADC_DRV_Start(ADC_INST); }您好,这里为尝试can接收多帧报文发送多帧报文是否会丢数据,使用evb板,配置can0,发送32邮箱,接受32邮箱,32个id报文10ms发送一次,同时发送,在没有使用软件缓冲区的时候,mcu发送进busy之后此时如果再接受此id的报文并且发送会丢失最新的一帧
2f3555d6-e5ee-4b9d-b98e-950a3e8c3684-image.png
程序里面记录那个rx通道接收和接收次数+1
f900b7a332fa2b3a53982f810378f2ce.png 7065356775a4f34332c4ca77e40345c6.png
发送的正好是上一帧的数值,差了32
这个是不是没有txfifo,想要接收许多数据的话应该怎么做
使用dma后,好像也不是固定32,
69cdb87369e8d5a98b3ab22ea9c59cfe.png
f0068d63-04d3-4117-b894-90f71b29190d-image.png
问题:
YTM32B1L05, 上下电测试中,会随机的出现ADC输出值异常情况。
故障出现后,不断电,故障会一直保持,断电再上电故障消失。
debug获取DMA目标地址数据发现,出现大量连续的 2048/1023 数值。中间掺杂几个正常的数据。
异常数据.jpg
ADC模块使用简介:
1)先 pTMR 触发 ADC采样0或1通道 DMA搬运,250组数据,再 pTMR 触发 ADC采样3或5通道 DMA搬运 1000组数据。
2)每500ms,执行1次 1)操作。
基本配置
ADC模块配置
/* adc_config0 */
const adc_converter_config_t adc_config0={
.clockDivider=0,
.startTime=48,
.sampleTime=200,
.overrunMode=false,
.autoOffEnable=false,
.waitEnable=false,
.trigger=ADC_TRIGGER_HARDWARE,
.align=ADC_ALIGN_RIGHT,
.resolution=ADC_RESOLUTION_12BIT,
.dmaWaterMark=1,
.dmaEnable=true,
.sequenceConfig={
.sequenceMode=ADC_CONV_LOOP,
.sequenceIntEnable=false,
.convIntEnable=false,
.readyIntEnable=false,
.ovrunIntEnable=false,
.sampIntEnable=false,
.channels={
ADC_INPUTCHAN_EXT3,
ADC_INPUTCHAN_EXT5,
},
.totalChannels=2,
},
.compareConfig={
.compareEnable=false,
.compareAllChannelEnable=false,
};
/* adc_config1 */
const adc_converter_config_t adc_config1={
.clockDivider=0,
.startTime=48,
.sampleTime=200,
.overrunMode=false,
.autoOffEnable=false,
.waitEnable=false,
.trigger=ADC_TRIGGER_HARDWARE,
.align=ADC_ALIGN_RIGHT,
.resolution=ADC_RESOLUTION_12BIT,
.dmaWaterMark=1,
.dmaEnable=true,
.sequenceConfig={
.sequenceMode=ADC_CONV_LOOP,
.sequenceIntEnable=false,
.convIntEnable=false,
.readyIntEnable=false,
.ovrunIntEnable=false,
.sampIntEnable=false,
.channels={
ADC_INPUTCHAN_EXT1,
ADC_INPUTCHAN_EXT0,
},
.totalChannels=2,
},
.compareConfig={
.compareEnable=false,
.compareAllChannelEnable=false,
};
DMA模块配置
dma_loop_transfer_config_t adcTransferConfigLoopConfig = {
.triggerLoopIterationCount=1000,
.srcOffsetEnable=false,
.dstOffsetEnable=true,
.triggerLoopOffset=0,
.transferLoopChnLinkEnable=false,
.transferLoopChnLinkNumber=0,
.triggerLoopChnLinkEnable=false,
.triggerLoopChnLinkNumber=0,
};
dma_transfer_config_t adcTransferConfig = {
.srcAddr=(uint32_t)0,
.destAddr=(uint32_t)0,
.srcOffset=0,
.destOffset=0x02U,
.srcTransferSize=DMA_TRANSFER_SIZE_2B,
.destTransferSize=DMA_TRANSFER_SIZE_2B,
.srcModulo=DMA_MODULO_OFF,
.destModulo=DMA_MODULO_OFF,
.transferLoopByteCount=4,
.srcLastAddrAdjust=4,
.destLastAddrAdjust=-4,
.interruptEnable=true,
.loopTransferConfig=&adcTransferConfigLoopConfig,
};
pTMR 配置
const ptmr_user_channel_config_t ptmr_channel_0={
.periodUnits=pTMR_PERIOD_UNITS_COUNTS,
.period=625,
.chainChannel=false,
.isInterruptEnabled=false,
};
时钟频率
内核&DMA 48M
ADC = 16M
pTMR = 8M
ADC链路配置
ADC链路配置.jpg
ADC链路启动
ADC链路启动.jpg
-
Announcements
Announcements regarding our community
-
Discussion & Question
A place to talk about whatever you want or ask a question
-
Blogs
Blog posts from individual members
快速上手云途开发生态
发帖前请查看
帮助改进和优化YT CONFIG TOOL,有机会抽取YTM32B1ME0 EVB哦...