RK3568 CAN波特率500K接收数据导致CPU4满载
最近调试RK3568 CAN时发现,当CAN作为接收端,在快速接收数据时会导致cpu4满载。down掉can口或者断开外设时恢复正常。并且问题只是在部门CPU版本上出现。在CAN接收中断中打印log,能发现log是按照接收数据的时间打印的。
驱动(rockchip_canfd.c)中关闭NAPI后正常,厂家的回复是“有的产品api不同,NAPI方式并不适用”。
// SPDX-License-Identifier: GPL-2.0
/** Copyright (c) 2020 Rockchip Electronics Co. Ltd.* Rockchip CANFD driver*/#include <linux/delay.h>
#include <linux/iopoll.h>
#include <linux/pinctrl/consumer.h>
#include <linux/clk.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include <linux/can/led.h>
#include <linux/reset.h>
#include <linux/pm_runtime.h>
#include <linux/rockchip/cpu.h>/* registers definition */
enum rockchip_canfd_reg {CAN_MODE = 0x00,CAN_CMD = 0x04,CAN_STATE = 0x08,CAN_INT = 0x0c,CAN_INT_MASK = 0x10,CAN_LOSTARB_CODE = 0x28,CAN_ERR_CODE = 0x2c,CAN_RX_ERR_CNT = 0x34,CAN_TX_ERR_CNT = 0x38,CAN_IDCODE = 0x3c,CAN_IDMASK = 0x40,CAN_TX_CHECK_FIC = 0x50,CAN_NBTP = 0x100,CAN_DBTP = 0x104,CAN_TDCR = 0x108,CAN_TSCC = 0x10c,CAN_TSCV = 0x110,CAN_TXEFC = 0x114,CAN_RXFC = 0x118,CAN_AFC = 0x11c,CAN_IDCODE0 = 0x120,CAN_IDMASK0 = 0x124,CAN_IDCODE1 = 0x128,CAN_IDMASK1 = 0x12c,CAN_IDCODE2 = 0x130,CAN_IDMASK2 = 0x134,CAN_IDCODE3 = 0x138,CAN_IDMASK3 = 0x13c,CAN_IDCODE4 = 0x140,CAN_IDMASK4 = 0x144,CAN_TXFIC = 0x200,CAN_TXID = 0x204,CAN_TXDAT0 = 0x208,CAN_TXDAT1 = 0x20c,CAN_TXDAT2 = 0x210,CAN_TXDAT3 = 0x214,CAN_TXDAT4 = 0x218,CAN_TXDAT5 = 0x21c,CAN_TXDAT6 = 0x220,CAN_TXDAT7 = 0x224,CAN_TXDAT8 = 0x228,CAN_TXDAT9 = 0x22c,CAN_TXDAT10 = 0x230,CAN_TXDAT11 = 0x234,CAN_TXDAT12 = 0x238,CAN_TXDAT13 = 0x23c,CAN_TXDAT14 = 0x240,CAN_TXDAT15 = 0x244,CAN_RXFIC = 0x300,CAN_RXID = 0x304,CAN_RXTS = 0x308,CAN_RXDAT0 = 0x30c,CAN_RXDAT1 = 0x310,CAN_RXDAT2 = 0x314,CAN_RXDAT3 = 0x318,CAN_RXDAT4 = 0x31c,CAN_RXDAT5 = 0x320,CAN_RXDAT6 = 0x324,CAN_RXDAT7 = 0x328,CAN_RXDAT8 = 0x32c,CAN_RXDAT9 = 0x330,CAN_RXDAT10 = 0x334,CAN_RXDAT11 = 0x338,CAN_RXDAT12 = 0x33c,CAN_RXDAT13 = 0x340,CAN_RXDAT14 = 0x344,CAN_RXDAT15 = 0x348,CAN_RXFRD = 0x400,CAN_TXEFRD = 0x500,
};enum {ROCKCHIP_CANFD_MODE = 0,ROCKCHIP_CAN_MODE,ROCKCHIP_RK3568_CAN_MODE,ROCKCHIP_RK3568_CAN_MODE_V2,
};#define DATE_LENGTH_12_BYTE (0x9)
#define DATE_LENGTH_16_BYTE (0xa)
#define DATE_LENGTH_20_BYTE (0xb)
#define DATE_LENGTH_24_BYTE (0xc)
#define DATE_LENGTH_32_BYTE (0xd)
#define DATE_LENGTH_48_BYTE (0xe)
#define DATE_LENGTH_64_BYTE (0xf)#define CAN_TX0_REQ BIT(0)
#define CAN_TX1_REQ BIT(1)
#define CAN_TX_REQ_FULL ((CAN_TX0_REQ) | (CAN_TX1_REQ))#define MODE_FDOE BIT(15)
#define MODE_BRSD BIT(13)
#define MODE_SPACE_RX BIT(12)
#define MODE_AUTO_RETX BIT(10)
#define MODE_RXSORT BIT(7)
#define MODE_TXORDER BIT(6)
#define MODE_RXSTX BIT(5)
#define MODE_LBACK BIT(4)
#define MODE_SILENT BIT(3)
#define MODE_SELF_TEST BIT(2)
#define MODE_SLEEP BIT(1)
#define RESET_MODE 0
#define WORK_MODE BIT(0)#define RX_FINISH_INT BIT(0)
#define TX_FINISH_INT BIT(1)
#define ERR_WARN_INT BIT(2)
#define RX_BUF_OV_INT BIT(3)
#define PASSIVE_ERR_INT BIT(4)
#define TX_LOSTARB_INT BIT(5)
#define BUS_ERR_INT BIT(6)
#define RX_FIFO_FULL_INT BIT(7)
#define RX_FIFO_OV_INT BIT(8)
#define BUS_OFF_INT BIT(9)
#define BUS_OFF_RECOVERY_INT BIT(10)
#define TSC_OV_INT BIT(11)
#define TXE_FIFO_OV_INT BIT(12)
#define TXE_FIFO_FULL_INT BIT(13)
#define WAKEUP_INT BIT(14)#define ERR_TYPE_MASK GENMASK(28, 26)
#define ERR_TYPE_SHIFT 26
#define BIT_ERR 0
#define STUFF_ERR 1
#define FORM_ERR 2
#define ACK_ERR 3
#define CRC_ERR 4
#define ERR_DIR_RX BIT(25)
#define ERR_LOC_MASK GENMASK(15, 0)/* Nominal Bit Timing & Prescaler Register (NBTP) */
#define NBTP_MODE_3_SAMPLES BIT(31)
#define NBTP_NSJW_SHIFT 24
#define NBTP_NSJW_MASK (0x7f << NBTP_NSJW_SHIFT)
#define NBTP_NBRP_SHIFT 16
#define NBTP_NBRP_MASK (0xff << NBTP_NBRP_SHIFT)
#define NBTP_NTSEG2_SHIFT 8
#define NBTP_NTSEG2_MASK (0x7f << NBTP_NTSEG2_SHIFT)
#define NBTP_NTSEG1_SHIFT 0
#define NBTP_NTSEG1_MASK (0x7f << NBTP_NTSEG1_SHIFT)/* Data Bit Timing & Prescaler Register (DBTP) */
#define DBTP_MODE_3_SAMPLES BIT(21)
#define DBTP_DSJW_SHIFT 17
#define DBTP_DSJW_MASK (0xf << DBTP_DSJW_SHIFT)
#define DBTP_DBRP_SHIFT 9
#define DBTP_DBRP_MASK (0xff << DBTP_DBRP_SHIFT)
#define DBTP_DTSEG2_SHIFT 5
#define DBTP_DTSEG2_MASK (0xf << DBTP_DTSEG2_SHIFT)
#define DBTP_DTSEG1_SHIFT 0
#define DBTP_DTSEG1_MASK (0x1f << DBTP_DTSEG1_SHIFT)/* Transmitter Delay Compensation Register (TDCR) */
#define TDCR_TDCO_SHIFT 1
#define TDCR_TDCO_MASK (0x3f << TDCR_TDCO_SHIFT)
#define TDCR_TDC_ENABLE BIT(0)#define TX_FD_ENABLE BIT(5)
#define TX_FD_BRS_ENABLE BIT(4)#define FIFO_ENABLE BIT(0)
#define RX_FIFO_CNT0_SHIFT 4
#define RX_FIFO_CNT0_MASK (0x7 << RX_FIFO_CNT0_SHIFT)
#define RX_FIFO_CNT1_SHIFT 5
#define RX_FIFO_CNT1_MASK (0x7 << RX_FIFO_CNT1_SHIFT)#define FORMAT_SHIFT 7
#define FORMAT_MASK (0x1 << FORMAT_SHIFT)
#define RTR_SHIFT 6
#define RTR_MASK (0x1 << RTR_SHIFT)
#define FDF_SHIFT 5
#define FDF_MASK (0x1 << FDF_SHIFT)
#define BRS_SHIFT 4
#define BRS_MASK (0x1 << BRS_SHIFT)
#define DLC_SHIFT 0
#define DLC_MASK (0xF << DLC_SHIFT)#define CAN_RF_SIZE 0x48
#define CAN_TEF_SIZE 0x8
#define CAN_TXEFRD_OFFSET(n) (CAN_TXEFRD + CAN_TEF_SIZE * (n))
#define CAN_RXFRD_OFFSET(n) (CAN_RXFRD + CAN_RF_SIZE * (n))#define CAN_RX_FILTER_MASK 0x1fffffff
#define NOACK_ERR_FLAG 0xc200800
#define CAN_BUSOFF_FLAG 0x20#define DRV_NAME "rockchip_canfd"/* rockchip_canfd private data structure */struct rockchip_canfd {struct can_priv can;struct device *dev;struct napi_struct napi;struct clk_bulk_data *clks;int num_clks;struct reset_control *reset;void __iomem *base;u32 irqstatus;unsigned long mode;int rx_fifo_shift;u32 rx_fifo_mask;bool txtorx;u32 tx_invalid[4];struct delayed_work tx_err_work;u32 noack_cnt;u32 delay_time_ms;
};static inline u32 rockchip_canfd_read(const struct rockchip_canfd *priv,enum rockchip_canfd_reg reg)
{return readl(priv->base + reg);
}static inline void rockchip_canfd_write(const struct rockchip_canfd *priv,enum rockchip_canfd_reg reg, u32 val)
{writel(val, priv->base + reg);
}static const struct can_bittiming_const rockchip_canfd_bittiming_const = {.name = DRV_NAME,.tseg1_min = 1,.tseg1_max = 128,.tseg2_min = 1,.tseg2_max = 128,.sjw_max = 128,.brp_min = 1,.brp_max = 256,.brp_inc = 2,
};static const struct can_bittiming_const rockchip_canfd_data_bittiming_const = {.name = DRV_NAME,.tseg1_min = 1,.tseg1_max = 32,.tseg2_min = 1,.tseg2_max = 16,.sjw_max = 16,.brp_min = 1,.brp_max = 256,.brp_inc = 2,
};static int set_reset_mode(struct net_device *ndev)
{struct rockchip_canfd *rcan = netdev_priv(ndev);reset_control_assert(rcan->reset);udelay(2);reset_control_deassert(rcan->reset);rockchip_canfd_write(rcan, CAN_MODE, 0);netdev_dbg(ndev, "%s MODE=0x%08x\n", __func__,rockchip_canfd_read(rcan, CAN_MODE));return 0;
}static int set_normal_mode(struct net_device *ndev)
{struct rockchip_canfd *rcan = netdev_priv(ndev);u32 val;val = rockchip_canfd_read(rcan, CAN_MODE);val |= WORK_MODE;rockchip_canfd_write(rcan, CAN_MODE, val);netdev_dbg(ndev, "%s MODE=0x%08x\n", __func__,rockchip_canfd_read(rcan, CAN_MODE));return 0;
}/* bittiming is called in reset_mode only */
static int rockchip_canfd_set_bittiming(struct net_device *ndev)
{struct rockchip_canfd *rcan = netdev_priv(ndev);const struct can_bittiming *bt = &rcan->can.bittiming;const struct can_bittiming *dbt = &rcan->can.data_bittiming;u16 brp, sjw, tseg1, tseg2;u32 reg_btp;brp = (bt->brp >> 1) - 1;sjw = bt->sjw - 1;tseg1 = bt->prop_seg + bt->phase_seg1 - 1;tseg2 = bt->phase_seg2 - 1;reg_btp = (brp << NBTP_NBRP_SHIFT) | (sjw << NBTP_NSJW_SHIFT) |(tseg1 << NBTP_NTSEG1_SHIFT) |(tseg2 << NBTP_NTSEG2_SHIFT);if (rcan->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)reg_btp |= NBTP_MODE_3_SAMPLES;rockchip_canfd_write(rcan, CAN_NBTP, reg_btp);if (rcan->can.ctrlmode & CAN_CTRLMODE_FD) {reg_btp = 0;brp = (dbt->brp >> 1) - 1;sjw = dbt->sjw - 1;tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1;tseg2 = dbt->phase_seg2 - 1;if (dbt->bitrate > 2200000) {u32 tdco;/* Equation based on Bosch's ROCKCHIP_CAN User Manual's* Transmitter Delay Compensation Section*/tdco = (rcan->can.clock.freq / dbt->bitrate) * 2 / 3;/* Max valid TDCO value is 63 */if (tdco > 63)tdco = 63;rockchip_canfd_write(rcan, CAN_TDCR,(tdco << TDCR_TDCO_SHIFT) |TDCR_TDC_ENABLE);}reg_btp |= (brp << DBTP_DBRP_SHIFT) |(sjw << DBTP_DSJW_SHIFT) |(tseg1 << DBTP_DTSEG1_SHIFT) |(tseg2 << DBTP_DTSEG2_SHIFT);if (rcan->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)reg_btp |= DBTP_MODE_3_SAMPLES;rockchip_canfd_write(rcan, CAN_DBTP, reg_btp);}if (bt->bitrate > 200000)rcan->delay_time_ms = 1;else if (bt->bitrate > 50000)rcan->delay_time_ms = 5;elsercan->delay_time_ms = 20;netdev_dbg(ndev, "%s NBTP=0x%08x, DBTP=0x%08x, TDCR=0x%08x\n", __func__,rockchip_canfd_read(rcan, CAN_NBTP),rockchip_canfd_read(rcan, CAN_DBTP),rockchip_canfd_read(rcan, CAN_TDCR));return 0;
}static int rockchip_canfd_get_berr_counter(const struct net_device *ndev,struct can_berr_counter *bec)
{struct rockchip_canfd *rcan = netdev_priv(ndev);int err;err = pm_runtime_get_sync(rcan->dev);if (err < 0) {netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",__func__, err);return err;}bec->rxerr = rockchip_canfd_read(rcan, CAN_RX_ERR_CNT);bec->txerr = rockchip_canfd_read(rcan, CAN_TX_ERR_CNT);pm_runtime_put(rcan->dev);netdev_dbg(ndev, "%s RX_ERR_CNT=0x%08x, TX_ERR_CNT=0x%08x\n", __func__,rockchip_canfd_read(rcan, CAN_RX_ERR_CNT),rockchip_canfd_read(rcan, CAN_TX_ERR_CNT));return 0;
}static int rockchip_canfd_start(struct net_device *ndev)
{struct rockchip_canfd *rcan = netdev_priv(ndev);u32 val;/* we need to enter the reset mode */set_reset_mode(ndev);rockchip_canfd_write(rcan, CAN_INT_MASK, 0);/* RECEIVING FILTER, accept all */rockchip_canfd_write(rcan, CAN_IDCODE, 0);rockchip_canfd_write(rcan, CAN_IDMASK, CAN_RX_FILTER_MASK);rockchip_canfd_write(rcan, CAN_IDCODE0, 0);rockchip_canfd_write(rcan, CAN_IDMASK0, CAN_RX_FILTER_MASK);rockchip_canfd_write(rcan, CAN_IDCODE1, 0);rockchip_canfd_write(rcan, CAN_IDMASK1, CAN_RX_FILTER_MASK);rockchip_canfd_write(rcan, CAN_IDCODE2, 0);rockchip_canfd_write(rcan, CAN_IDMASK2, CAN_RX_FILTER_MASK);rockchip_canfd_write(rcan, CAN_IDCODE3, 0);rockchip_canfd_write(rcan, CAN_IDMASK3, CAN_RX_FILTER_MASK);rockchip_canfd_write(rcan, CAN_IDCODE4, 0);rockchip_canfd_write(rcan, CAN_IDMASK4, CAN_RX_FILTER_MASK);/* set mode */val = rockchip_canfd_read(rcan, CAN_MODE);/* rx fifo enable */rockchip_canfd_write(rcan, CAN_RXFC,rockchip_canfd_read(rcan, CAN_RXFC) | FIFO_ENABLE);/* Mode */val |= MODE_FDOE;/* Loopback Mode */if (rcan->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)val |= MODE_SELF_TEST | MODE_LBACK;/* Listen-only mode */if (rcan->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)val |= MODE_SILENT;rockchip_canfd_write(rcan, CAN_MODE, val);rockchip_canfd_set_bittiming(ndev);set_normal_mode(ndev);rcan->can.state = CAN_STATE_ERROR_ACTIVE;netdev_dbg(ndev, "%s MODE=0x%08x, INT_MASK=0x%08x\n", __func__,rockchip_canfd_read(rcan, CAN_MODE),rockchip_canfd_read(rcan, CAN_INT_MASK));return 0;
}static int rockchip_canfd_stop(struct net_device *ndev)
{struct rockchip_canfd *rcan = netdev_priv(ndev);rcan->can.state = CAN_STATE_STOPPED;/* we need to enter reset mode */set_reset_mode(ndev);/* disable all interrupts */rockchip_canfd_write(rcan, CAN_INT_MASK, 0xffff);netdev_dbg(ndev, "%s MODE=0x%08x, INT_MASK=0x%08x\n", __func__,rockchip_canfd_read(rcan, CAN_MODE),rockchip_canfd_read(rcan, CAN_INT_MASK));return 0;
}static int rockchip_canfd_set_mode(struct net_device *ndev,enum can_mode mode)
{int err;switch (mode) {case CAN_MODE_START:err = rockchip_canfd_start(ndev);if (err) {netdev_err(ndev, "starting CAN controller failed!\n");return err;}if (netif_queue_stopped(ndev))netif_wake_queue(ndev);break;default:return -EOPNOTSUPP;}return 0;
}static void rockchip_canfd_tx_err_delay_work(struct work_struct *work)
{struct rockchip_canfd *rcan =container_of(work, struct rockchip_canfd, tx_err_work.work);struct net_device *ndev = dev_get_drvdata(rcan->dev);rockchip_canfd_write(rcan, CAN_MODE,rockchip_canfd_read(rcan, CAN_MODE) | MODE_SPACE_RX);rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ);rockchip_canfd_write(rcan, CAN_MODE,rockchip_canfd_read(rcan, CAN_MODE) & (~MODE_SPACE_RX));rcan->noack_cnt++;schedule_delayed_work(&rcan->tx_err_work, msecs_to_jiffies(rcan->delay_time_ms));if (rcan->noack_cnt > 50) {cancel_delayed_work(&rcan->tx_err_work);rockchip_canfd_write(rcan, CAN_INT_MASK, 0xffff);can_bus_off(ndev);rcan->noack_cnt = 0;}
}/* transmit a CAN message* message layout in the sk_buff should be like this:* xx xx xx xx ff ll 00 11 22 33 44 55 66 77* [ can_id ] [flags] [len] [can data (up to 8 bytes]*/
static int rockchip_canfd_start_xmit(struct sk_buff *skb,struct net_device *ndev)
{struct rockchip_canfd *rcan = netdev_priv(ndev);struct canfd_frame *cf = (struct canfd_frame *)skb->data;u32 id, dlc;u32 cmd = CAN_TX0_REQ;int i;unsigned long flags;if (can_dropped_invalid_skb(ndev, skb))return NETDEV_TX_OK;netif_stop_queue(ndev);if (rockchip_canfd_read(rcan, CAN_CMD) & CAN_TX0_REQ)cmd = CAN_TX1_REQ;/* Watch carefully on the bit sequence */if (cf->can_id & CAN_EFF_FLAG) {/* Extended CAN ID format */id = cf->can_id & CAN_EFF_MASK;dlc = can_len2dlc(cf->len) & DLC_MASK;dlc |= FORMAT_MASK;/* Extended frames remote TX request */if (cf->can_id & CAN_RTR_FLAG)dlc |= RTR_MASK;} else {/* Standard CAN ID format */id = cf->can_id & CAN_SFF_MASK;dlc = can_len2dlc(cf->len) & DLC_MASK;/* Standard frames remote TX request */if (cf->can_id & CAN_RTR_FLAG)dlc |= RTR_MASK;}if ((rcan->can.ctrlmode & CAN_CTRLMODE_FD) && can_is_canfd_skb(skb)) {dlc |= TX_FD_ENABLE;if (cf->flags & CANFD_BRS)dlc |= TX_FD_BRS_ENABLE;}if (rcan->txtorx && rcan->mode <= ROCKCHIP_RK3568_CAN_MODE && cf->can_id & CAN_EFF_FLAG)rockchip_canfd_write(rcan, CAN_MODE,rockchip_canfd_read(rcan, CAN_MODE) | MODE_RXSTX);elserockchip_canfd_write(rcan, CAN_MODE,rockchip_canfd_read(rcan, CAN_MODE) & (~MODE_RXSTX));if (!rcan->txtorx && rcan->mode <= ROCKCHIP_RK3568_CAN_MODE && cf->can_id & CAN_EFF_FLAG) {/* Two frames are sent consecutively.* Before the first frame is tx finished,* the register of the second frame is configured.* Don't be interrupted in the middle.*/local_irq_save(flags);rockchip_canfd_write(rcan, CAN_TXID, rcan->tx_invalid[1]);rockchip_canfd_write(rcan, CAN_TXFIC, rcan->tx_invalid[0]);rockchip_canfd_write(rcan, CAN_TXDAT0, rcan->tx_invalid[2]);rockchip_canfd_write(rcan, CAN_TXDAT1, rcan->tx_invalid[3]);rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ);rockchip_canfd_write(rcan, CAN_TXID, id);rockchip_canfd_write(rcan, CAN_TXFIC, dlc);for (i = 0; i < cf->len; i += 4)rockchip_canfd_write(rcan, CAN_TXDAT0 + i,*(u32 *)(cf->data + i));can_put_echo_skb(skb, ndev, 0);rockchip_canfd_write(rcan, CAN_CMD, CAN_TX1_REQ);local_irq_restore(flags);return NETDEV_TX_OK;}rockchip_canfd_write(rcan, CAN_TXID, id);rockchip_canfd_write(rcan, CAN_TXFIC, dlc);for (i = 0; i < cf->len; i += 4)rockchip_canfd_write(rcan, CAN_TXDAT0 + i,*(u32 *)(cf->data + i));can_put_echo_skb(skb, ndev, 0);rockchip_canfd_write(rcan, CAN_MODE,rockchip_canfd_read(rcan, CAN_MODE) | MODE_SPACE_RX);rockchip_canfd_write(rcan, CAN_CMD, cmd);rockchip_canfd_write(rcan, CAN_MODE,rockchip_canfd_read(rcan, CAN_MODE) & (~MODE_SPACE_RX));schedule_delayed_work(&rcan->tx_err_work, msecs_to_jiffies(rcan->delay_time_ms));return NETDEV_TX_OK;
}static int rockchip_canfd_rx(struct net_device *ndev)
{struct rockchip_canfd *rcan = netdev_priv(ndev);struct net_device_stats *stats = &ndev->stats;struct canfd_frame *cf;struct sk_buff *skb;u32 id_rockchip_canfd, dlc;int i = 0;u32 __maybe_unused ts, ret;u32 data[16];dlc = rockchip_canfd_read(rcan, CAN_RXFRD);id_rockchip_canfd = rockchip_canfd_read(rcan, CAN_RXFRD);ts = rockchip_canfd_read(rcan, CAN_RXFRD);for (i = 0; i < ARRAY_SIZE(data); i++)data[i] = rockchip_canfd_read(rcan, CAN_RXFRD);if (rcan->mode <= ROCKCHIP_RK3568_CAN_MODE) {/* may be an empty frame */if (!dlc && !id_rockchip_canfd)return 1;if (rcan->txtorx) {if (rockchip_canfd_read(rcan, CAN_TX_CHECK_FIC) & FORMAT_MASK) {ret = rockchip_canfd_read(rcan, CAN_TXID) & CAN_SFF_MASK;if ((id_rockchip_canfd == ret) && !(dlc & FORMAT_MASK))rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC,ts | CAN_TX0_REQ);return 1;}}}/* create zero'ed CAN frame buffer */if (dlc & FDF_MASK)skb = alloc_canfd_skb(ndev, &cf);elseskb = alloc_can_skb(ndev, (struct can_frame **)&cf);if (!skb) {stats->rx_dropped++;return 1;}/* Change CAN data length format to socketCAN data format */if (dlc & FDF_MASK)cf->len = can_dlc2len(dlc & DLC_MASK);elsecf->len = get_can_dlc(dlc & DLC_MASK);/* Change CAN ID format to socketCAN ID format */if (dlc & FORMAT_MASK) {/* The received frame is an Extended format frame */cf->can_id = id_rockchip_canfd;cf->can_id |= CAN_EFF_FLAG;if (dlc & RTR_MASK)cf->can_id |= CAN_RTR_FLAG;} else {/* The received frame is a standard format frame */cf->can_id = id_rockchip_canfd;if (dlc & RTR_MASK)cf->can_id |= CAN_RTR_FLAG;}if (dlc & BRS_MASK)cf->flags |= CANFD_BRS;if (!(cf->can_id & CAN_RTR_FLAG)) {/* Change CAN data format to socketCAN data format */for (i = 0; i < cf->len; i += 4)*(u32 *)(cf->data + i) = data[i / 4];}stats->rx_packets++;stats->rx_bytes += cf->len;netif_rx(skb);can_led_event(ndev, CAN_LED_EVENT_RX);return 1;
}static int rockchip_canfd_get_rx_fifo_cnt(struct net_device *ndev)
{struct rockchip_canfd *rcan = netdev_priv(ndev);int quota = 0;if (read_poll_timeout_atomic(rockchip_canfd_read, quota,(quota & rcan->rx_fifo_mask) >> rcan->rx_fifo_shift,0, 500000, false, rcan, CAN_RXFC))netdev_dbg(ndev, "Warning: get fifo cnt failed\n");quota = (quota & rcan->rx_fifo_mask) >> rcan->rx_fifo_shift;return quota;
}/* rockchip_canfd_rx_poll - Poll routine for rx packets (NAPI)* @napi: napi structure pointer* @quota: Max number of rx packets to be processed.** This is the poll routine for rx part.* It will process the packets maximux quota value.** Return: number of packets received*/
static int rockchip_canfd_rx_poll(struct napi_struct *napi, int quota)
{struct net_device *ndev = napi->dev;struct rockchip_canfd *rcan = netdev_priv(ndev);int work_done = 0;quota = rockchip_canfd_get_rx_fifo_cnt(ndev);if (quota > 6)quota = 6;if (quota) {while (work_done < quota)work_done += rockchip_canfd_rx(ndev);}if (work_done)can_led_event(ndev, CAN_LED_EVENT_RX);if (work_done < 6) {napi_complete_done(napi, work_done);rockchip_canfd_write(rcan, CAN_INT_MASK, 0);}return work_done;
}static void rockchip_canfd_tx_retry(struct net_device *ndev, u32 isr)
{struct rockchip_canfd *rcan = netdev_priv(ndev);u32 err_code = rockchip_canfd_read(rcan, CAN_ERR_CODE);u32 data[4], mode;int i = 0;if ((isr & TX_LOSTARB_INT) || ((!(err_code & 0x2000000)) && (err_code & 0x1ff0000))) {mode = rockchip_canfd_read(rcan, CAN_MODE);for (i = 0; i < ARRAY_SIZE(data); i++)data[i] = rockchip_canfd_read(rcan, CAN_TXFIC + i * 4);rockchip_canfd_write(rcan, CAN_INT_MASK, 0xffff);rockchip_canfd_start(ndev);rockchip_canfd_write(rcan, CAN_MODE, mode);for (i = 0; i < ARRAY_SIZE(data); i++)rockchip_canfd_write(rcan, CAN_TXFIC + i * 4, data[i]);}
}static int rockchip_canfd_err(struct net_device *ndev, u32 isr)
{struct rockchip_canfd *rcan = netdev_priv(ndev);struct net_device_stats *stats = &ndev->stats;struct can_frame *cf;struct sk_buff *skb;unsigned int rxerr, txerr;u32 sta_reg;skb = alloc_can_err_skb(ndev, &cf);rxerr = rockchip_canfd_read(rcan, CAN_RX_ERR_CNT);txerr = rockchip_canfd_read(rcan, CAN_TX_ERR_CNT);sta_reg = rockchip_canfd_read(rcan, CAN_STATE);if (skb) {cf->data[6] = txerr;cf->data[7] = rxerr;}if (isr & BUS_OFF_INT) {rcan->can.state = CAN_STATE_BUS_OFF;rcan->can.can_stats.bus_off++;cf->can_id |= CAN_ERR_BUSOFF;} else if (isr & ERR_WARN_INT) {rcan->can.can_stats.error_warning++;rcan->can.state = CAN_STATE_ERROR_WARNING;/* error warning state */if (likely(skb)) {cf->can_id |= CAN_ERR_CRTL;cf->data[1] = (txerr > rxerr) ?CAN_ERR_CRTL_TX_WARNING :CAN_ERR_CRTL_RX_WARNING;cf->data[6] = txerr;cf->data[7] = rxerr;}} else if (isr & PASSIVE_ERR_INT) {rcan->can.can_stats.error_passive++;rcan->can.state = CAN_STATE_ERROR_PASSIVE;/* error passive state */cf->can_id |= CAN_ERR_CRTL;cf->data[1] = (txerr > rxerr) ?CAN_ERR_CRTL_TX_WARNING :CAN_ERR_CRTL_RX_WARNING;cf->data[6] = txerr;cf->data[7] = rxerr;}if (rcan->can.state >= CAN_STATE_BUS_OFF ||((sta_reg & CAN_BUSOFF_FLAG) == CAN_BUSOFF_FLAG)) {cancel_delayed_work(&rcan->tx_err_work);rockchip_canfd_write(rcan, CAN_INT_MASK, 0xffff);can_bus_off(ndev);}stats->rx_packets++;stats->rx_bytes += cf->can_dlc;netif_rx(skb);return 0;
}static irqreturn_t rockchip_canfd_interrupt(int irq, void *dev_id)
{struct net_device *ndev = (struct net_device *)dev_id;struct rockchip_canfd *rcan = netdev_priv(ndev);struct net_device_stats *stats = &ndev->stats;u32 err_int = ERR_WARN_INT | RX_BUF_OV_INT | PASSIVE_ERR_INT |BUS_ERR_INT | BUS_OFF_INT;u32 isr;u32 dlc = 0;u32 quota, work_done = 0;isr = rockchip_canfd_read(rcan, CAN_INT);if (isr & TX_FINISH_INT) {cancel_delayed_work(&rcan->tx_err_work);dlc = rockchip_canfd_read(rcan, CAN_TXFIC);/* transmission complete interrupt */if (dlc & FDF_MASK)stats->tx_bytes += can_dlc2len(dlc & DLC_MASK);elsestats->tx_bytes += (dlc & DLC_MASK);stats->tx_packets++;if (rcan->txtorx && rcan->mode <= ROCKCHIP_RK3568_CAN_MODE && dlc & FORMAT_MASK) {rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, FORMAT_MASK);quota = rockchip_canfd_get_rx_fifo_cnt(ndev);if (quota) {while (work_done < quota)work_done += rockchip_canfd_rx(ndev);}if (rockchip_canfd_read(rcan, CAN_TX_CHECK_FIC) & CAN_TX0_REQ)rockchip_canfd_write(rcan, CAN_CMD, CAN_TX1_REQ);rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, 0);}if (read_poll_timeout_atomic(rockchip_canfd_read, quota,!(quota & 0x3),0, 5000000, false, rcan, CAN_CMD))netdev_err(ndev, "Warning: wait tx req timeout!\n");rockchip_canfd_write(rcan, CAN_CMD, 0);can_get_echo_skb(ndev, 0);netif_wake_queue(ndev);can_led_event(ndev, CAN_LED_EVENT_TX);rcan->noack_cnt = 0;}if ((isr & RX_FINISH_INT) || (isr & RX_FIFO_OV_INT) || (isr & RX_FIFO_FULL_INT)) {if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2) {//rockchip_canfd_write(rcan, CAN_INT_MASK, 0x1);work_done = 0;quota = (rockchip_canfd_read(rcan, CAN_RXFC) &rcan->rx_fifo_mask) >>rcan->rx_fifo_shift;if (quota) {while (work_done < quota)work_done += rockchip_canfd_rx(ndev);}} else {work_done = 0;quota = (rockchip_canfd_read(rcan, CAN_RXFC) &rcan->rx_fifo_mask) >>rcan->rx_fifo_shift;if (quota) {while (work_done < quota)work_done += rockchip_canfd_rx(ndev);}}}if (isr & err_int) {/* error interrupt */if (rockchip_canfd_err(ndev, isr))netdev_err(ndev, "can't allocate buffer - clearing pending interrupts\n");}rockchip_canfd_tx_retry(ndev, isr);rockchip_canfd_write(rcan, CAN_INT, isr);return IRQ_HANDLED;
}static int rockchip_canfd_open(struct net_device *ndev)
{struct rockchip_canfd *rcan = netdev_priv(ndev);int err;/* common open */err = open_candev(ndev);if (err)return err;err = pm_runtime_get_sync(rcan->dev);if (err < 0) {netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",__func__, err);goto exit;}err = rockchip_canfd_start(ndev);if (err) {netdev_err(ndev, "could not start CAN peripheral\n");goto exit_can_start;}can_led_event(ndev, CAN_LED_EVENT_OPEN);
// if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2)
// napi_enable(&rcan->napi);netif_start_queue(ndev);netdev_dbg(ndev, "%s\n", __func__);return 0;exit_can_start:pm_runtime_put(rcan->dev);
exit:close_candev(ndev);return err;
}static int rockchip_canfd_close(struct net_device *ndev)
{struct rockchip_canfd *rcan = netdev_priv(ndev);netif_stop_queue(ndev);
// if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2)
// napi_disable(&rcan->napi);rockchip_canfd_stop(ndev);close_candev(ndev);can_led_event(ndev, CAN_LED_EVENT_STOP);pm_runtime_put(rcan->dev);cancel_delayed_work_sync(&rcan->tx_err_work);netdev_dbg(ndev, "%s\n", __func__);return 0;
}static const struct net_device_ops rockchip_canfd_netdev_ops = {.ndo_open = rockchip_canfd_open,.ndo_stop = rockchip_canfd_close,.ndo_start_xmit = rockchip_canfd_start_xmit,.ndo_change_mtu = can_change_mtu,
};/*** rockchip_canfd_suspend - Suspend method for the driver* @dev: Address of the device structure** Put the driver into low power mode.* Return: 0 on success and failure value on error*/
static int __maybe_unused rockchip_canfd_suspend(struct device *dev)
{struct net_device *ndev = dev_get_drvdata(dev);if (netif_running(ndev)) {netif_stop_queue(ndev);netif_device_detach(ndev);rockchip_canfd_stop(ndev);}return pm_runtime_force_suspend(dev);
}/*** rockchip_canfd_resume - Resume from suspend* @dev: Address of the device structure** Resume operation after suspend.* Return: 0 on success and failure value on error*/
static int __maybe_unused rockchip_canfd_resume(struct device *dev)
{struct net_device *ndev = dev_get_drvdata(dev);int ret;ret = pm_runtime_force_resume(dev);if (ret) {dev_err(dev, "pm_runtime_force_resume failed on resume\n");return ret;}if (netif_running(ndev)) {ret = rockchip_canfd_start(ndev);if (ret) {dev_err(dev, "rockchip_canfd_chip_start failed on resume\n");return ret;}netif_device_attach(ndev);netif_start_queue(ndev);}return 0;
}/*** rockchip_canfd_runtime_suspend - Runtime suspend method for the driver* @dev: Address of the device structure** Put the driver into low power mode.* Return: 0 always*/
static int __maybe_unused rockchip_canfd_runtime_suspend(struct device *dev)
{struct net_device *ndev = dev_get_drvdata(dev);struct rockchip_canfd *rcan = netdev_priv(ndev);clk_bulk_disable_unprepare(rcan->num_clks, rcan->clks);return 0;
}/*** rockchip_canfd_runtime_resume - Runtime resume from suspend* @dev: Address of the device structure** Resume operation after suspend.* Return: 0 on success and failure value on error*/
static int __maybe_unused rockchip_canfd_runtime_resume(struct device *dev)
{struct net_device *ndev = dev_get_drvdata(dev);struct rockchip_canfd *rcan = netdev_priv(ndev);int ret;ret = clk_bulk_prepare_enable(rcan->num_clks, rcan->clks);if (ret) {dev_err(dev, "Cannot enable clock.\n");return ret;}return 0;
}static const struct dev_pm_ops rockchip_canfd_dev_pm_ops = {SET_SYSTEM_SLEEP_PM_OPS(rockchip_canfd_suspend, rockchip_canfd_resume)SET_RUNTIME_PM_OPS(rockchip_canfd_runtime_suspend,rockchip_canfd_runtime_resume, NULL)
};static const struct of_device_id rockchip_canfd_of_match[] = {{.compatible = "rockchip,canfd-1.0",.data = (void *)ROCKCHIP_CANFD_MODE},{.compatible = "rockchip,can-2.0",.data = (void *)ROCKCHIP_CAN_MODE},{.compatible = "rockchip,rk3568-can-2.0",.data = (void *)ROCKCHIP_RK3568_CAN_MODE},{},
};
MODULE_DEVICE_TABLE(of, rockchip_canfd_of_match);static int rockchip_canfd_probe(struct platform_device *pdev)
{struct net_device *ndev;struct rockchip_canfd *rcan;struct resource *res;void __iomem *addr;int err, irq;irq = platform_get_irq(pdev, 0);if (irq < 0) {dev_err(&pdev->dev, "could not get a valid irq\n");return -ENODEV;}res = platform_get_resource(pdev, IORESOURCE_MEM, 0);addr = devm_ioremap_resource(&pdev->dev, res);if (IS_ERR(addr))return -EBUSY;ndev = alloc_candev(sizeof(struct rockchip_canfd), 1);if (!ndev) {dev_err(&pdev->dev, "could not allocate memory for CANFD device\n");return -ENOMEM;}rcan = netdev_priv(ndev);/* register interrupt handler */err = devm_request_irq(&pdev->dev, irq, rockchip_canfd_interrupt,0, ndev->name, ndev);if (err) {dev_err(&pdev->dev, "request_irq err: %d\n", err);return err;}rcan->reset = devm_reset_control_array_get(&pdev->dev, false, false);if (IS_ERR(rcan->reset)) {if (PTR_ERR(rcan->reset) != -EPROBE_DEFER)dev_err(&pdev->dev, "failed to get canfd reset lines\n");return PTR_ERR(rcan->reset);}rcan->num_clks = devm_clk_bulk_get_all(&pdev->dev, &rcan->clks);if (rcan->num_clks < 1)return -ENODEV;rcan->mode = (unsigned long)of_device_get_match_data(&pdev->dev);if ((cpu_is_rk3566() || cpu_is_rk3568()) && (rockchip_get_cpu_version() == 3))rcan->mode = ROCKCHIP_RK3568_CAN_MODE_V2;rcan->base = addr;rcan->can.clock.freq = clk_get_rate(rcan->clks[0].clk);rcan->dev = &pdev->dev;rcan->can.state = CAN_STATE_STOPPED;switch (rcan->mode) {case ROCKCHIP_CANFD_MODE:rcan->can.bittiming_const = &rockchip_canfd_bittiming_const;rcan->can.data_bittiming_const = &rockchip_canfd_data_bittiming_const;rcan->can.do_set_mode = rockchip_canfd_set_mode;rcan->can.do_get_berr_counter = rockchip_canfd_get_berr_counter;rcan->can.do_set_bittiming = rockchip_canfd_set_bittiming;rcan->can.do_set_data_bittiming = rockchip_canfd_set_bittiming;rcan->can.ctrlmode = CAN_CTRLMODE_FD;/* IFI CANFD can do both Bosch FD and ISO FD */rcan->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |CAN_CTRLMODE_FD;rcan->rx_fifo_shift = RX_FIFO_CNT0_SHIFT;rcan->rx_fifo_mask = RX_FIFO_CNT0_MASK;break;case ROCKCHIP_CAN_MODE:case ROCKCHIP_RK3568_CAN_MODE:case ROCKCHIP_RK3568_CAN_MODE_V2:rcan->can.bittiming_const = &rockchip_canfd_bittiming_const;rcan->can.do_set_mode = rockchip_canfd_set_mode;rcan->can.do_get_berr_counter = rockchip_canfd_get_berr_counter;rcan->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING |CAN_CTRLMODE_LISTENONLY |CAN_CTRLMODE_LOOPBACK |CAN_CTRLMODE_3_SAMPLES;rcan->rx_fifo_shift = RX_FIFO_CNT0_SHIFT;rcan->rx_fifo_mask = RX_FIFO_CNT0_MASK;break;default:return -EINVAL;}if (rcan->mode == ROCKCHIP_CAN_MODE) {rcan->rx_fifo_shift = RX_FIFO_CNT1_SHIFT;rcan->rx_fifo_mask = RX_FIFO_CNT1_MASK;}if (device_property_read_u32_array(&pdev->dev,"rockchip,tx-invalid-info",rcan->tx_invalid, 4))rcan->txtorx = 1;if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2) {rcan->txtorx = 0;//netif_napi_add(ndev, &rcan->napi, rockchip_canfd_rx_poll, 6);}ndev->netdev_ops = &rockchip_canfd_netdev_ops;ndev->irq = irq;ndev->flags |= IFF_ECHO;rcan->can.restart_ms = 100;rcan->noack_cnt = 0;irq_set_affinity_hint(irq, get_cpu_mask(num_online_cpus() - 1));INIT_DELAYED_WORK(&rcan->tx_err_work, rockchip_canfd_tx_err_delay_work);platform_set_drvdata(pdev, ndev);SET_NETDEV_DEV(ndev, &pdev->dev);pm_runtime_enable(&pdev->dev);err = pm_runtime_get_sync(&pdev->dev);if (err < 0) {dev_err(&pdev->dev, "%s: pm_runtime_get failed(%d)\n",__func__, err);goto err_pmdisable;}err = register_candev(ndev);if (err) {dev_err(&pdev->dev, "registering %s failed (err=%d)\n",DRV_NAME, err);goto err_disableclks;}devm_can_led_init(ndev);return 0;err_disableclks:pm_runtime_put(&pdev->dev);
err_pmdisable:pm_runtime_disable(&pdev->dev);free_candev(ndev);return err;
}static int rockchip_canfd_remove(struct platform_device *pdev)
{struct net_device *ndev = platform_get_drvdata(pdev);
// struct rockchip_canfd *rcan = netdev_priv(ndev);unregister_netdev(ndev);pm_runtime_disable(&pdev->dev);
// if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2)
// netif_napi_del(&rcan->napi);free_candev(ndev);return 0;
}static struct platform_driver rockchip_canfd_driver = {.driver = {.name = DRV_NAME,.pm = &rockchip_canfd_dev_pm_ops,.of_match_table = rockchip_canfd_of_match,},.probe = rockchip_canfd_probe,.remove = rockchip_canfd_remove,
};
module_platform_driver(rockchip_canfd_driver);MODULE_AUTHOR("Elaine Zhang <zhangqing@rock-chips.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Rockchip CANFD Drivers");
相关文章:

RK3568 CAN波特率500K接收数据导致CPU4满载
最近调试RK3568 CAN时发现,当CAN作为接收端,在快速接收数据时会导致cpu4满载。down掉can口或者断开外设时恢复正常。并且问题只是在部门CPU版本上出现。在CAN接收中断中打印log,能发现log是按照接收数据的时间打印的。 驱动(rockchip_canfd…...

AI实战 | 使用元器打造浪漫仪式小管家
浪漫仪式小管家 以前我们曾经打造过学习助手和待办助手,但这一次,我们决定创造一个与众不同的智能体,而浪漫将成为我们的主题。我们选择浪漫作为主题,是因为我们感到在之前的打造过程中缺乏了一些仪式感,无法给对方带来真正的惊喜。因此,这一次我们计划慢慢调试,将它发…...

什么是隐马尔可夫模型?
文章目录 一、说明二、玩具HMM:5′拼接位点识别三、那么,隐藏了什么?四、查找最佳状态路径五、超越最佳得分对齐六、制作更逼真的模型七、收获 关键词:hidden markov model 一、说明 被称为隐马尔可夫模型的统计模型是计算生物学…...

qt中使用qsqlite连接数据库,却没有在本地文件夹中生成db文件
exe运行起来之后,发现没有在exe文件夹下生成数据库文件,,之前可以,但中间莫名其妙不行了,代码如下 // 建立和SQlite数据库的连接database QSqlDatabase::addDatabase("QSQLITE");// 设置数据库文件的名字da…...

Django的‘通用视图TemplateView’
使用通用视图的好处是:如果有一个html需要展示,不需要写view视图函数,直接写好url即可。 使用通用视图的步骤如下: 1、编辑项目urls.py文件 from django.views.generic import TemplateView 在该文件的映射表中添加:…...

java功能实现在某个时间范围之内输出true,不在某个范围输出false,时间精确到分钟
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DateTimeChecker { private static final Logger log LoggerFactory.getLogger(DateTimeChecker.class); /** * 检查当前时间是否在指定的小时和分钟范围内。 * * param startHour 开…...

macbook屏幕录制技巧,这2个方法请你收好
在当今数字化时代,屏幕录制成为了一项不可或缺的技能,无论是教学演示、游戏直播,还是软件操作教程,屏幕录制都能帮助我们更直观地传达信息。MacBook作为苹果公司的标志性产品,其屏幕录制功能也备受用户关注。本文将详细…...

vue-loader
Vue Loader 是一个 webpack 的 loader,它允许你以一种名为单文件组件 (SFCs)的格式撰写 Vue 组件 起步 安装 npm install vue --save npm install webpack webpack-cli style-loader css-loader html-webpack-plugin vue-loader vue-template-compiler webpack…...

IO系列(十) -TCP 滑动窗口原理介绍(上)
一、摘要 之前在上分享网络编程知识文章的时候,有网友写下一条留言:“可以写写一篇关于 TCP 滑动窗口原理的文章吗?”。 当时没有立即回复,经过查询多方资料,发现这个 TCP 真的非常非常的复杂,就像一个清…...

IPython 使用技巧整理
IPython 是一个增强的 Python 交互式 shell,提供了许多实用的功能和特性,使得 Python 编程和数据科学工作变得更加便捷和高效。以下是一些 IPython 的使用技巧整理: 1. 自动补全和查询 Tab 补全:在 IPython 中,你可以…...

Python 引入中文py文件
目录 背景 思路 importlib介绍 使用方法 1.导入内置库 importlib.util 2.创建模块规格对象 spec importlib.util.spec_from_file_location("example_module", "example.py") 3.创建模块对象 module importlib.util.module_from_spec(spec) …...

qt 实现模拟实际物体带速度的移动(水平、垂直、斜角度)——————附带完整代码
文章目录 0 效果1 原理1.1 图片旋转1.2 物体按照现实中的实际距离带真实速度移动 2 完整实现2.1 将车辆按钮封装为一个类:2.2 调用方法 3 完整代码参考 0 效果 实现后的效果如下 可以显示属性(继承自QToolButton): 鼠标悬浮显示文字 按钮…...

驱动开发(三):内核层控制硬件层
驱动开发系列文章: 驱动开发(一):驱动代码的基本框架 驱动开发(二):创建字符设备驱动 驱动开发(三):内核层控制硬件层 ←本文 目录…...

企业邮箱大附件无法上传?无法确认接收状态?这样解决就行
Outlook邮箱作为最常用的邮箱系统,被全世界企业采用作为内部通用沟通方式,但Outlook邮箱却有着明显的使用缺陷,如邮箱大附件上传障碍及附件接收无提示等。 1、企业邮箱大附件无法上传 Outlook企业邮箱大附件的上传上限一般是50M,…...

Kotlin 数据类(Data Class)
Kotlin 数据类(Data Class)是一种特别用于持有数据的类。它们简化了数据类的创建,并提供了一些自动生成的方法。下面详细介绍 Kotlin 数据类的原理和使用方法。 数据类的定义 Kotlin 中的数据类使用 data 关键字定义。例如: da…...

gridview自带编辑功能如何判断用户修改的值的合法性
在使用GridView的编辑功能更新值时,确保输入的值合法性是十分重要的。为了实现这一点,你可以在GridView的RowUpdating事件中加入代码来检查用户输入的值。如果发现输入的值不合法,你可以取消更新操作并向用户显示错误消息。下面是如何实现的步…...

设计模式-结构型-06-桥接模式
1、传统方式解决手机操作问题 现在对不同手机类型的不同品牌实现操作编程(比如:开机、关机、上网,打电话等),如图: UML 类图 问题分析 扩展性问题(类爆炸):如果我们再…...

安泰电压放大器的选型原则是什么
电压放大器是电子电路中常用的一种器件,主要用于放大输入电压信号。在选型电压放大器时,需要考虑以下几个原则。 根据应用需求确定放大倍数。放大倍数是指输出电压与输入电压之间的倍数关系,也称为增益。不同的应用场景对放大倍数的要求不同&…...

方法分享 |公网IP怎么指定非433端口实现https访问
公网IP可以通过指定非443端口实现HTTPS访问。在网络配置中,虽然HTTPS协议默认使用443端口,但没有规定不能在其他端口上实施HTTPS服务。使用非标准端口进行HTTPS通信需要正确配置服务器和SSL证书,并确保客户端能够连接到指定的端口。下面说明如…...

vue实现拖拽元素;vuedraggable拖拽插件
效果图: 中文文档 以下代码可直接复制使用 安装依赖 npm i -S vuedraggable使用 <template><div class"container"><div>使用flex竖轴布局 <br>handle".mover" 可拖拽的class类名 <br>filter".forbid&qu…...

Javascript介绍
Javascript 定义:一门简单的浏览器可解析的语言 作用:与HTML相结合使用,使我们的网页变得更加酷炫 发展史: 1.1992年,Nombase公司开发出来,校验表单,起名c--,后来更名为&#…...

毕业答辩PPT:如何在短时间内高效准备?
提起PPT,大家的第一反应就是痛苦。经常接触PPT的学生党和打工人,光看到这3个字母,就已经开始头痛了: 1、PPT内容框架与文案挑战重重,任务艰巨,耗费大量精力。 2、PPT的排版技能要求高,并非易事…...

树结构与算法-杨辉三角形的两种实现
什么是杨辉三角形 本文旨在讨论普通杨辉三角形的两种实现方式:迭代法和递归法。我们不详细讲解杨辉三角形的数学问题,只研究其代码实现。 杨辉三角形大致如下图: 杨辉三角形的规律 通过对杨辉三角形的图形分析,我们可以看到这几点…...

【机器学习】智能创意工厂:机器学习驱动的AIGC,打造未来内容新生态
🚀时空传送门 🔍机器学习在AIGC中的核心技术📕深度学习🎈生成对抗网络(GANs) 🚀机器学习在AIGC中的具体应用🍀图像生成与编辑⭐文本生成与对话系统🌠音频生成与语音合成 …...

Python - 一个恶意脚本
Python - 恶意脚本 使用此脚本或修改前请注意以下几点: 系统资源:大量模拟键盘和鼠标事件可能会占用大量系统资源,会导致其他应用程序运行缓慢或崩溃。 隐私和安全:如果此脚本在未经用户同意的情况下运行,它可能侵犯…...

SFNC —— 采集控制(四)
系列文章目录 SFNC —— 标准特征命名约定(一) SFNC —— 设备控制(二) SFNC —— 图像格式控制(三) SFNC —— 采集控制(四) 文章目录 系列文章目录5、采集控制(Acquisi…...

AUTOSAR学习
文章目录 前言1. 什么是autosar?1.1 AP(自适应平台autosar)1.2 CP(经典平台autosar)1.3 我的疑问 2. 为什么会有autosar3.autosar的架构3.1 CP的架构3.1.1 应用软件层3.1.2 运行时环境3.1.3 基础软件层 3.2 AP的架构 4. 参考资料 …...

区区微服务,何足挂齿?
背景 睿哥前天吩咐我去了解一下微服务,我本来想周末看的,结果周末没带电脑,所以只能周一看了。刚刚我就去慕课网看了相关的视频,然后写一篇文章总结一下。这篇文章算是基础理论版,等我之后进行更多的实践,…...

数据结构 ->反转链表
工作原理 初始化: cur 指向传入的节点 node,即链表的头节点。prv 初始化为 NULL,用于存储当前节点的前一个节点。 循环反转: 在 while 循环中,当 cur 不为空时执行循环体。保存当前节点的下一个节点:使用 t…...

Unity基础(一)unity的下载与安装
目录 一:下载与安装 1.官网下载地址 2.推荐直接下载UnityHub 3.选择编辑器版本(推荐长期支持版) 4.在UnityHub安装选择相应的模块 二:创建项目 简介: Unity 是一款广泛应用的跨平台游戏开发引擎。 它具有以下显著特点: 强大的跨平台能力:能将开发的游…...