解决一个I2C读写问题

之前写关于I2C相关的文章

排查一个触摸屏驱动问题

MTK 平台TP调试遇坑

1、问题

今天遇到一个问题,我们有一个芯片,I2C读写失败,导致录音有问题,而且是偶现的。

log提示看到是返回 -6

<3>[  730.336308]  (3)[2085:tinycap]es7243_read error2, ret = -6.

下面流程找一下这个 -6 是从哪里来的

2、I2c 发送流程

i2c-core.c

调用发送函数

/*** __i2c_transfer - unlocked flavor of i2c_transfer* @adap: Handle to I2C bus* @msgs: One or more messages to execute before STOP is issued to* terminate the operation; each message begins with a START.* @num: Number of messages to be executed.** Returns negative errno, else the number of messages executed.** Adapter lock must be held when calling this function. No debug logging* takes place. adap->algo->master_xfer existence isn't checked.*/
int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{unsigned long orig_jiffies;int ret, try;if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))return -EOPNOTSUPP;/* i2c_trace_msg gets enabled when tracepoint i2c_transfer gets* enabled.  This is an efficient way of keeping the for-loop from* being executed when not needed.*/if (static_key_false(&i2c_trace_msg)) {int i;for (i = 0; i < num; i++)if (msgs[i].flags & I2C_M_RD)trace_i2c_read(adap, &msgs[i], i);elsetrace_i2c_write(adap, &msgs[i], i);}/* Retry automatically on arbitration loss */orig_jiffies = jiffies;for (ret = 0, try = 0; try <= adap->retries; try++) {ret = adap->algo->master_xfer(adap, msgs, num);if (ret != -EAGAIN)break;if (time_after(jiffies, orig_jiffies + adap->timeout))break;}if (static_key_false(&i2c_trace_msg)) {int i;for (i = 0; i < ret; i++)if (msgs[i].flags & I2C_M_RD)trace_i2c_reply(adap, &msgs[i], i);trace_i2c_result(adap, i, ret);}return ret;
}
EXPORT_SYMBOL(__i2c_transfer);

里面有一句

ret = adap->algo->master_xfer(adap, msgs, num);

这里需要找到初始化的位置,这种指针初始化的位置,一般都是和平台设备相关的,这里也是一个技巧,初学者看到这类指针一般都会比较懵。

所以,就开始去找吧。

因为我用的是MTK平台,所以需要去找到MTK平台相关里面初始化的这个指针

i2c-mt65xx.c (D:\source\kernel-4.4\drivers\i2c\busses) line 755 :  .master_xfer = mtk_i2c_transfer,

在文件

i2c-mt65xx.c

这里初始化了

static const struct i2c_algorithm mtk_i2c_algorithm = {.master_xfer = mtk_i2c_transfer,.functionality = mtk_i2c_functionality,
};

然后再调用发送函数

static int mtk_i2c_transfer(struct i2c_adapter *adap,struct i2c_msg msgs[], int num)
{int ret;int left_num = num;struct mtk_i2c *i2c = i2c_get_adapdata(adap);ret = mtk_i2c_clock_enable(i2c);if (ret)return ret;i2c->auto_restart = i2c->dev_comp->auto_restart;/* checking if we can skip restart and optimize using WRRD mode */if (i2c->auto_restart && num == 2) {if (!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD) &&msgs[0].addr == msgs[1].addr) {i2c->auto_restart = 0;}}if (i2c->auto_restart && num >= 2 && i2c->speed_hz > MAX_FS_MODE_SPEED)/* ignore the first restart irq after the master code,* otherwise the first transfer will be discarded.*/i2c->ignore_restart_irq = true;elsei2c->ignore_restart_irq = false;while (left_num--) {if (!msgs->buf) {dev_dbg(i2c->dev, "data buffer is NULL.\n");ret = -EINVAL;goto err_exit;}if (msgs->flags & I2C_M_RD)i2c->op = I2C_MASTER_RD;elsei2c->op = I2C_MASTER_WR;if (!i2c->auto_restart) {if (num > 1) {/* combined two messages into one transaction */i2c->op = I2C_MASTER_WRRD;left_num--;}}/* len <= 8: use fifo mode, len > 8: use DMA mode. */ret = mtk_i2c_do_transfer(i2c, msgs, num, left_num);if (ret < 0)goto err_exit;msgs++;}/* the return value is number of executed messages */ret = num;err_exit:mtk_i2c_clock_disable(i2c);return ret;
}

3、返回 值的代码位置

在文件

i2c-mt65xx.c

中的函数

static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,int num, int left_num)
{bool dma_en;u8 *data_buf;u16 data_len;u16 read_len;u16 addr_reg;u16 start_reg;u16 control_reg;u16 restart_flag = 0;u32 reg_4g_mode;dma_addr_t rpaddr = 0;dma_addr_t wpaddr = 0;int ret;i2c->irq_stat = 0;if (i2c->auto_restart)restart_flag = I2C_RS_TRANSFER;reinit_completion(&i2c->msg_complete);control_reg = readw(i2c->base + OFFSET_CONTROL) &~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);if ((i2c->speed_hz > 400000) || (left_num >= 1))control_reg |= I2C_CONTROL_RS;if (i2c->op == I2C_MASTER_WRRD)control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;writew(control_reg, i2c->base + OFFSET_CONTROL);/* set start condition */if (i2c->speed_hz <= 100000)writew(I2C_ST_START_CON, i2c->base + OFFSET_EXT_CONF);elsewritew(I2C_FS_START_CON, i2c->base + OFFSET_EXT_CONF);addr_reg = msgs->addr << 1;if (i2c->op == I2C_MASTER_RD)addr_reg |= 0x1;writew(addr_reg, i2c->base + OFFSET_SLAVE_ADDR);/* Clear interrupt status */writew(restart_flag | I2C_HS_NACKERR | I2C_ACKERR |I2C_TRANSAC_COMP, i2c->base + OFFSET_INTR_STAT);writew(I2C_FIFO_ADDR_CLR, i2c->base + OFFSET_FIFO_ADDR_CLR);/* Enable interrupt */writew(restart_flag | I2C_HS_NACKERR | I2C_ACKERR |I2C_TRANSAC_COMP, i2c->base + OFFSET_INTR_MASK);/* Set transfer and transaction len */if (i2c->op == I2C_MASTER_WRRD) {if (i2c->dev_comp->aux_len_reg) {writew(msgs->len, i2c->base + OFFSET_TRANSFER_LEN);writew((msgs + 1)->len, i2c->base +OFFSET_TRANSFER_LEN_AUX);} else {writew(msgs->len | ((msgs + 1)->len) << 8,i2c->base + OFFSET_TRANSFER_LEN);}writew(I2C_WRRD_TRANAC_VALUE, i2c->base + OFFSET_TRANSAC_LEN);} else {writew(msgs->len, i2c->base + OFFSET_TRANSFER_LEN);writew(num, i2c->base + OFFSET_TRANSAC_LEN);}/* Prepare buffer data to start transfer */if (msgs->len > I2C_FIFO_SIZE || (i2c->op == I2C_MASTER_WRRD &&(msgs + 1)->len > I2C_FIFO_SIZE)) {dma_en = true;if (i2c->op == I2C_MASTER_RD) {writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);writel(I2C_DMA_CON_RX, i2c->pdmabase + OFFSET_CON);rpaddr = dma_map_single(i2c->dev, msgs->buf,msgs->len, DMA_FROM_DEVICE);if (dma_mapping_error(i2c->dev, rpaddr))return -ENOMEM;if (i2c->dev_comp->support_33bits) {reg_4g_mode = mtk_i2c_set_4g_mode(rpaddr);writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE);}writel((u32)rpaddr, i2c->pdmabase + OFFSET_RX_MEM_ADDR);writel(msgs->len, i2c->pdmabase + OFFSET_RX_LEN);} else if (i2c->op == I2C_MASTER_WR) {writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);writel(I2C_DMA_CON_TX, i2c->pdmabase + OFFSET_CON);wpaddr = dma_map_single(i2c->dev, msgs->buf,msgs->len, DMA_TO_DEVICE);if (dma_mapping_error(i2c->dev, wpaddr))return -ENOMEM;if (i2c->dev_comp->support_33bits) {reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr);writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);}writel((u32)wpaddr, i2c->pdmabase + OFFSET_TX_MEM_ADDR);writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN);} else {writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_INT_FLAG);writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_CON);wpaddr = dma_map_single(i2c->dev, msgs->buf,msgs->len, DMA_TO_DEVICE);if (dma_mapping_error(i2c->dev, wpaddr))return -ENOMEM;rpaddr = dma_map_single(i2c->dev, (msgs + 1)->buf,(msgs + 1)->len, DMA_FROM_DEVICE);if (dma_mapping_error(i2c->dev, rpaddr)) {dma_unmap_single(i2c->dev, wpaddr,msgs->len, DMA_TO_DEVICE);return -ENOMEM;}if (i2c->dev_comp->support_33bits) {reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr);writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);reg_4g_mode = mtk_i2c_set_4g_mode(rpaddr);writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE);}writel((u32)wpaddr, i2c->pdmabase + OFFSET_TX_MEM_ADDR);writel((u32)rpaddr, i2c->pdmabase + OFFSET_RX_MEM_ADDR);writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN);writel((msgs + 1)->len, i2c->pdmabase + OFFSET_RX_LEN);}if (i2c->op != I2C_MASTER_RD)writel(I2C_DMA_START_EN, i2c->pdmabase + OFFSET_EN);} else {dma_en = false;if (i2c->op != I2C_MASTER_RD) {data_buf = msgs->buf;data_len = msgs->len;while (data_len--)writew_relaxed(*(data_buf++), i2c->base + OFFSET_DATA_PORT);}}if (!i2c->auto_restart) {start_reg = I2C_TRANSAC_START;} else {start_reg = I2C_TRANSAC_START | I2C_RS_MUL_TRIG;if (left_num >= 1)start_reg |= I2C_RS_MUL_CNFG;}writew(start_reg, i2c->base + OFFSET_START);if (dma_en && i2c->op == I2C_MASTER_RD)writel(I2C_DMA_START_EN, i2c->pdmabase + OFFSET_EN);ret = wait_for_completion_timeout(&i2c->msg_complete,i2c->adap.timeout);/* Clear interrupt mask */writew(~(restart_flag | I2C_HS_NACKERR | I2C_ACKERR |I2C_TRANSAC_COMP), i2c->base + OFFSET_INTR_MASK);if (dma_en) {if (i2c->op == I2C_MASTER_WR) {dma_unmap_single(i2c->dev, wpaddr,msgs->len, DMA_TO_DEVICE);} else if (i2c->op == I2C_MASTER_RD) {dma_unmap_single(i2c->dev, rpaddr,msgs->len, DMA_FROM_DEVICE);} else {dma_unmap_single(i2c->dev, wpaddr, msgs->len,DMA_TO_DEVICE);dma_unmap_single(i2c->dev, rpaddr, (msgs + 1)->len,DMA_FROM_DEVICE);}}if (ret == 0) {dev_dbg(i2c->dev, "addr: %x, transfer timeout\n", msgs->addr);mtk_i2c_init_hw(i2c);return -ETIMEDOUT;}completion_done(&i2c->msg_complete);if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);mtk_i2c_init_hw(i2c);return -ENXIO;}if (!dma_en && i2c->op != I2C_MASTER_WR) {data_buf = (i2c->op == I2C_MASTER_RD) ? msgs->buf :(msgs + 1)->buf;data_len = (i2c->op == I2C_MASTER_RD) ? msgs->len :(msgs + 1)->len;read_len = (readw(i2c->base + OFFSET_FIFO_STAT) >> 4) & 0xf;if (read_len == data_len) {while (data_len--)*(data_buf++) = readw_relaxed(i2c->base + OFFSET_DATA_PORT);} else {dev_dbg(i2c->dev, "data_len %x, read_len %x, fifo read len error\n",data_len, read_len);mtk_i2c_init_hw(i2c);return -EIO;}}return 0;
}

下面这段代码

 if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);mtk_i2c_init_hw(i2c);return -ENXIO;}

宏定义

errno-base.h

#define ENXIO   6 /* No such device or address */

表示就是找不到设备,没有应答

我用逻辑分析仪抓波形,确实存在没有应答的情况下打印了上面的错误日志。

解决

问题日志

<6>[ 1594.422871]  (3)[1663:AudioInMic][ES7243]: es7243_pcm_startup() line: 444 start.
<6>[ 1594.432778]  (3)[1663:AudioInMic][ES7243]: es7243_pcm_startup() line: 444 start.
<6>[ 1594.432902]  (3)[1663:AudioInMic][ES7243]: es7243_pcm_hw_params() line: 472 es7243_pcm_hw_params
<6>[ 1594.432918]  (3)[1663:AudioInMic][ES7243]: es7243_set_bias_level() line: 568 level:1
<6>[ 1594.433367]  (3)[1663:AudioInMic][ES7243]: es7243_write() line: 161 es7243_write reg:0x00 val:0x09 ok
<6>[ 1594.433741]  (0)[1663:AudioInMic][ES7243]: es7243_write() line: 161 es7243_write reg:0x06 val:0x18 ok
<6>[ 1594.434121]  (2)[1663:AudioInMic][ES7243]: es7243_write() line: 161 es7243_write reg:0x07 val:0x80 ok
<6>[ 1594.434506]  (0)[1663:AudioInMic][ES7243]: es7243_write() line: 161 es7243_write reg:0x01 val:0x0c ok
<6>[ 1594.434886]  (0)[1663:AudioInMic][ES7243]: es7243_write() line: 161 es7243_write reg:0x02 val:0x10 ok
<6>[ 1594.435288]  (2)[1663:AudioInMic][ES7243]: es7243_write() line: 161 es7243_write reg:0x03 val:0x04 ok
<6>[ 1594.435682]  (3)[1663:AudioInMic][ES7243]: es7243_write() line: 161 es7243_write reg:0x04 val:0x02 ok
<6>[ 1594.436136]  (1)[1663:AudioInMic][ES7243]: es7243_write() line: 161 es7243_write reg:0x05 val:0x1a ok
<6>[ 1594.436574]  (3)[1663:AudioInMic][ES7243]: es7243_write() line: 161 es7243_write reg:0x09 val:0x3f ok
<6>[ 1594.437004]  (0)[1663:AudioInMic][ES7243]: es7243_write() line: 161 es7243_write reg:0x06 val:0x00 ok
<6>[ 1594.437424]  (3)[1663:AudioInMic][ES7243]: es7243_write() line: 161 es7243_write reg:0x05 val:0x36 ok
<3>[ 1594.437676]  (3)[1663:AudioInMic]es7243_write 13 error->[REG-0x08,val-0x07]
<3>[ 1594.437907]  (3)[1663:AudioInMic]es7243_read error1
<3>[ 1594.438220]  (3)[1663:AudioInMic]es7243_write 13 error->[REG-0x01,val-0x8c]
<6>[ 1594.438246]  (3)[1663:AudioInMic][ES7243]: es7243_update_bits() line: 175 value:12
<3>[ 1594.438951]  (3)[1663:AudioInMic]es7243_read error2, ret = -6.
<6>[ 1594.438990]  (3)[1663:AudioInMic][ES7243]: es7243_pcm_hw_params() line: 538 es7243_pcm_hw_params538 -- Reg 08 ----> 0x0!
<3>[ 1594.439477]  (3)[1663:AudioInMic]es7243_read error2, ret = -6.
<6>[ 1594.439510]  (3)[1663:AudioInMic][ES7243]: es7243_pcm_hw_params() line: 540 es7243_pcm_hw_params540 -- Reg 05 ----> 0x0!

复现了十几把,发现每次都是刚开始I2C可以读写,后面再读写的时候,就容易出现I2C操作失败的情况。

FAE给的答复是

  • I2C走线是否有其他干扰

  • I2C有没有加RC滤波电路

硬件已经确定了,想再修改硬件可能性比较小,也比较麻烦,硬件测量了I2C波形,也没有发现异常。故此,还是想在软件上做规避。

我猜测可能是芯片操作过快,芯片没有来得及反应,而且每次操作开始I2C都是可以读写的,所以就想在读写函数中阻塞一会会来规避这个问题。

patch

diff --git a/kernel-4.4/sound/soc/codecs/es7243.c b/kernel-4.4/sound/soc/codecs/es7243.c
index 272f5dbf88..0e6a1e6bcc 100755
--- a/kernel-4.4/sound/soc/codecs/es7243.c
+++ b/kernel-4.4/sound/soc/codecs/es7243.c
@@ -32,6 +32,7 @@#include <sound/tlv.h>#include <sound/initval.h>#include <linux/regmap.h>
+#include <linux/delay.h>#ifdef CONFIG_OF#include <linux/of.h>#include <linux/of_irq.h>
@@ -127,6 +128,7 @@ static int es7243_read(u8 reg, u8 *rt_value, struct i2c_client *client)read_cmd[0] = reg;cmd_len = 1;+       udelay(2000);if (client->adapter == NULL)pr_err("es7243_read client->adapter==NULL\n");@@ -141,6 +143,7 @@ static int es7243_read(u8 reg, u8 *rt_value, struct i2c_client *client)pr_err("es7243_read error2, ret = %d.\n", ret);return -1;}
+ES7243_DEBUG("es7243_read OK\n");return 0;}
@@ -153,12 +156,14 @@ static int es7243_write(u8 reg, unsigned char value, struct i2c_client *client)write_cmd[0] = reg;write_cmd[1] = value;+       udelay(2000);ret = i2c_master_send(client, write_cmd, 2);if (ret != 2) {pr_err("es7243_write %x error->[REG-0x%02x,val-0x%02x]\n",client->addr,reg,value);return -1;}ES7243_DEBUG("es7243_write reg:0x%.2x val:0x%.2x ok \n",reg,value);
+return 0;}

修改后,验证了十几把,确实没有再发现问题,如果再有问题的话,再分析。

推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎转发,在看,评论~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466556.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用多媒体库 Bass.dll 播放 mp3 [9] - 绘制波形图

本例效果图:代码文件:unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls, ExtCtrls, ComCtrls;typeTForm1 class(TForm)OpenDialog1: TOpenDialog;PaintBox1: TPaintBox;Button1: TButton;Button2: TBut…

我是如何使用wireshark软件的

长按二维码识别关注技术共享|资料共享|沟通交流01简介这篇文章介绍一个好用的抓包工具Wireshark&#xff0c; 用来获取网络数据封包&#xff0c;包括HTTP、TCP、UDP等网络协议包。开始界面wireshark是捕获机器上的某一块网卡的网络包&#xff0c;当你的机器上有多块网卡的时候&…

BZOJ4681 [jsoi2010]旅行

时间限制&#xff1a; 3S空间限制&#xff1a; 256M具体思路:DPf[i][j][k]表示1-i,前L条路上用了 j条,L后的路上换了k条的最小代价枚举一下L就有了一个复杂度O(nlognk^3)的做法AC代码#include<bits/stdc.h> using namespace std; #define INF 100000000 #define P pair&l…

IIC踩过的坑

读取IT8563WE时&#xff0c;读取第一次正确&#xff0c;第二次错误&#xff0c;第三次正确&#xff0c;第四次错误。。。。。。看到读取成功之后&#xff0c;SDA信号没有被正确拉高&#xff0c;电平大概只有一半。再次读取&#xff0c;主机设置读模式时&#xff0c;从机会发送N…

1万字30张图说清TCP协议

本篇文章较长&#xff0c;大家先看下目录1、简介2、TCP协议头3、TCP 数据包的编号&#xff08;SEQ&#xff09;4、三次握手建立连接5、四次挥手断开连接6、TCP可靠性的保证7、滑动窗口技术9、窗口滑动的数据重发9、TCP 流控制10、网线“断”了怎么办01简介TCP(Transmission Con…

Spring源码解析(二)BeanDefinition的Resource定位

IOC容器的初始化过程主要包括BeanDefinition的Resource定位、载入和注册。在实际项目中我们基本上操作的都是ApplicationContex的实现&#xff0c;我们比较熟悉的ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebapplicationContext等。ApplicationCo…

单片机(MCU)如何才能不死机之对齐访问(Aligned Access)

从一个结构体说起。如下&#xff0c;在 STM32F0 的程序中&#xff0c;我们定义了一个结构体My_Struct &#xff0c;那么这个结构体占用多少内存呢&#xff1f;struct Struct_Def { uint8_t Var_B; uint16_t Var_W0; uint16_t Var_W1; uint32_t Var_DW; }; struct Struct_Def My…

小米的隔空充电,看起来好酷

昨天是1月29号&#xff0c;昨天小米发布了一个隔空充电技术&#xff0c;很火爆&#xff0c;大胆想&#xff0c;如果有一条无线充电的高速公路&#xff0c;那电动汽车还担心没有电吗&#xff1f;—— 雷总的微博原文隔空充电技术&#xff1a;如科幻电影一般&#xff0c;拿着手机…

同事用void把我给秀翻了!

1、聊一聊今天跟大家推荐的这首歌最近应该挺火的&#xff0c;不过没办法插入AGA的原版歌曲&#xff0c;大家觉得不错可以去找找原版歌曲收录一下。昨天建立了"最后一个bug"技术交流群,由于群成员超过200就无法直接通过群二维码加入&#xff0c;如果大家想加入扫描下面…

Spring Boot之自定义属性

选择Spring Boot主要是考虑到它既能兼顾Spring的强大功能&#xff0c;还能实现快速开发的便捷。我想大多数人也是出于这个原因选择了Spring Boot,如果不是特殊应用场景&#xff0c;就只需要在application.properties中完成一些属性配置就能开启各模块的应用。而不像传统的XML配…

一个老工程师的工作经历和思考

在这里不敢以”资深”工程师自居&#xff0c;因为学历和技术水平确实一般。为什么说“老”呢&#xff1f;因为工作时间确实够长&#xff0c;已经接近20年。下面把自身工作和学习经历和大家分享一下&#xff0c;使初学者能够得到一些有用的东西。2000年毕业&#xff0c;机械电子…

电子工程师都在看什么?送你一份“修炼宝典”

现如今&#xff0c;形形色色的公众号如繁星一般让人眼花缭乱。近几年科技的飞速发展&#xff0c;让更多人开始关注科技&#xff0c;甚至成为极客。然而学习是永无止境的&#xff0c;如何才能追赶如此高速的发展&#xff1f;曾经&#xff0c;我也是不知道去看哪些&#xff0c;便…

DataCleaner(4.5)第一章

Part1. Introduction to DataCleaner  介绍DataCleaner |--What is data quality(DQ)  数据质量&#xff1f;|--What is data profiling?   数据分析&#xff1f;|--What is datastore?     数据存储&#xff1f;   Composite datastore   综合性数据存储 |…

约瑟夫斯问题-java版数组解法和链表解法

10个人围成一圈&#xff0c;从1到10编号&#xff0c;从1开始数&#xff0c;数到3或3的倍数的位置&#xff0c;则该位置的人出局&#xff0c;求最后剩下哪一个号&#xff1f; 数组解法&#xff1a; 数组存放数组&#xff1a;a[10]存在1到10编号人 数组遍历到尾部又从头遍历&…

少写点if-else吧,它的效率有多低你知道吗?

# 干了这碗鸡汤我要再和生活死磕几年。要么我就毁灭&#xff0c;要么我就注定铸就辉煌。如果有一天&#xff0c;你发现我在平庸面前低了头&#xff0c;请向我开炮。--杰克凯鲁亚克if-else涉及到分支预测的概念&#xff0c;关于分支预测上篇文章《虚函数真的就那么慢吗&#xff…

为什么不能在中断上半部休眠?

这是一个老生常谈的问题。我们先简单说下什么是中断「因为最近在群里看到有人竟然不懂什么是中断」。中断是计算机里面非常核心的东西&#xff0c;我们可以跑OS&#xff0c;可以多任务运行都因为中断的存在。假设你是一个CPU&#xff0c;你正在睡觉。你突然觉得肚子疼&#xff…

j.u.c系列(08)---之并发工具类:CountDownLatch

写在前面 CountDownLatch所描述的是”在完成一组正在其他线程中执行的操作之前&#xff0c;它允许一个或多个线程一直等待“&#xff1a;用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法&#xff0c;所以在当前计数到达零之前&#xff0c;await 方法会一直受…

巧用1个GPIO控制2个LED显示4种状态

很多电子产品有状态指示灯&#xff0c;比如电视机&#xff1a;待机状态亮红灯开机状态亮绿灯实现起来很简单&#xff0c;微控制器MCU的两个GPIO分别控制就行&#xff1a;不过资源总是紧张的&#xff0c;有时候会碰到GPIO不够用的情况。如果只用1个GPIO&#xff0c;可不可以实现…

大大大大数怎么求余?C语言

问题&#xff1a;一个特别大的数除以23求余数用C语言应该怎么算啊&#xff1f;比如23232323232323232323232323232323232323232323232323232323233除以23&#xff0c;怎么算余数&#xff1f;数据类型在计算机的存储是有大小限制的&#xff0c;所以才出现了大数求余这种问题&…

程序员因拒绝带电脑回家工作被开除!获赔19.4万元

近日&#xff0c;男子拒绝春节带电脑回家工作被开除的消息&#xff0c;成为了不少网友关注的焦点&#xff0c;引发网友共鸣。因为春节拒绝带工作电脑回家被开除&#xff0c;上海一位软件工程师起诉公司获赔19.4万元。2月2日&#xff0c;据上海浦东法院公众号消息&#xff0c;该…