OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2703|回复: 6

为什么IMX6ULL的GPT2定时器选ipg_clk时钟源,计时的快慢由Linux系统的繁忙程度决定?

[复制链接]

1

主题

15

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2017-9-27
在线时间
6 小时
发表于 2022-6-19 13:00:02 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 zlk1214 于 2022-6-19 13:33 编辑

CPU型号:MCIMX6Y2CVM08AB
系统环境:正点原子出厂状态(uboot2016.03 + linux4.1.15内核 + busybox根文件系统)

经检查,CCM_CCGR0寄存器的gpt2_bus_clk_enable位为0,GPT2的时钟没有开,认定GPT2没有被系统占用,可以自己使用。
于是在CCM_CCGR0中打开GPT2的时钟:CCM_CCGR_CG12(gpt2_bus_clk_enable)=1或3。(测试发现不打开这个,GPT2的寄存器就无法读写)
GPT2的时钟源选择Peripheral Clock (ipg_clk)时钟,该时钟源的倍频路径如下:
(pre_periph_clk_sel=0)PLL2(528MHz) -> GLITCHLESS MUX(=0) -> ahb_podf divider=4 -> ipg_podf divider=2 -> IPG_CLK_ROOT -> PERCLK_PODF divider=1 -> PERIPH_CLK_ROOT
IPG_CLK_ROOT=528MHz/4/2=66MHz
PERIPH_CLK_ROOT=66MHz/1=66MHz
因此,理论上GPT2的输入时钟源频率为66MHz,这和正点原子驱动教程里讲的一样。

编写一个利用定时器溢出中断扫描8位数码管(由两片74HC595驱动)的程序。定时器每溢出一次,点亮一位数码管。
实际测试发现,Linux系统越繁忙,数码管扫描速度越快。系统越空闲,数码管扫描速度越慢。
例如,串口命令行空闲时,数码管扫描速度非常慢,几秒钟才扫描一位。
在串口中输入命令时,数码管扫描速度稍快一些,大约一秒钟扫描一位。
运行一个冒泡排序的C程序,数码管扫描速度非常快,一秒钟能扫描整个数码管好几遍。按Ctrl+C程序一退出,扫描马上就慢下来了。
把GPT2_CNT的值打印出来,可以明显发现定时器计数有时快,有时慢。
测试还发现,GPT2如果选择Crystal oscillator as Reference Clock (ipg_clk_24M)时钟,且GPT2_CR_EN_24M=1,那么定时器完全不走时。

令GPT2_OCR1=19999,GPT2_PR=3299,理论上定时器的溢出频率是66MHz/(19999+1)/(3299+1)=1Hz,即每秒钟溢出一次。
实际测试:Linux系统空闲时3秒一次(时钟源实际频率约24MHz),Linux系统繁忙时约0.3秒一次(时钟源实际频率约2.4MHz)。
这都和时钟源的理论频率66MHz相差很远。

板上晶振的频率是24MHz,而PLL2的倍频系数是不可编程的,是固定的528MHz。那为何GPT2的ipg_clk时钟源会这么不稳定呢?而且ipg_clk_24M这个时钟源完全无法使用!
谁能帮我解释一下呢?

附:一些寄存器的值。
[ 4735.694601] CCM->CCGR0=0xcfc03f0f
[ 4735.697943] CCM->CCGR1=0x3fff0030
[ 4735.701263] GPT2->CR=0x00000000
[ 4735.706800] GPT2->IR=0x01
[ 4735.709446] GPT2->SR=0x00
[ 4735.731338] gpt2 irq number=213
[ 4735.736296] GPT2->CR=0x00000041

[ 4796.616176] CCM_CBCDR=0x00018d00
[ 4796.619431]   [IPG_PODF]=1 (divide by 2)
[ 4796.625408]   [AHB_PODF]=3 (divide by 4)
[ 4796.629358]   [GLITCHLESS MUX]=[PERIPH_CLK_SEL]|[PLL_BYPASS_EN2]=0|0=0
[ 4796.637781] CCM_CBCMR=0x25228324
[ 4796.641844]   [PRE_PERIPH_CLK_SEL]=0
[ 4796.646642] CCM_CSCMR1=0x14902140
[ 4796.649984]   [PERCLK_PODF]=0 (divide by 1)
[ 4796.655812] CCM_CMEOR=0x7fffffff
[ 4796.659065]   [MOD_EN_OV_GPT]=1

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

15

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2017-9-27
在线时间
6 小时
 楼主| 发表于 2022-6-19 13:01:23 | 显示全部楼层
数码管驱动代码:
  1. #include <asm/io.h>
  2. #include <asm/uaccess.h>
  3. #include <linux/cdev.h>
  4. #include <linux/fs.h>
  5. #include <linux/of.h>
  6. #include <linux/of_address.h>
  7. #include <linux/of_irq.h>
  8. #include <linux/gpio/consumer.h>
  9. #include <linux/interrupt.h>
  10. #include <linux/module.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/slab.h>

  13. #define _BV(n) (1ull << (n))

  14. #define GPT_CR_EN_24M _BV(10)
  15. #define GPT_CR_CLKSRC_Pos 6
  16. #define GPT_CR_ENMOD _BV(1)
  17. #define GPT_CR_EN _BV(0)
  18. #define GPT_SR_OF1 _BV(0)
  19. #define GPT_IR_OF1IE _BV(0)

  20. struct imx6ull_gpt
  21. {
  22.         u32 CR;
  23.         u32 PR;
  24.         u32 SR;
  25.         u32 IR;
  26.         u32 OCR1;
  27.         u32 OCR2;
  28.         u32 OCR3;
  29.         u32 ICR1;
  30.         u32 ICR2;
  31.         u32 CNT;
  32. };

  33. struct test_data
  34. {
  35.         struct gpio_descs *gpios;
  36.         dev_t devid;
  37.         struct cdev cdev;
  38.         struct class *class;
  39.         struct device *device;
  40.        
  41.         struct imx6ull_gpt __iomem *GPT2;
  42.         u32 __iomem (*CCGR)[2];
  43.         unsigned int irq;
  44.        
  45.         int number;
  46.         int number_bit;
  47.         int number_tmp;
  48. };

  49. struct test_file
  50. {
  51.         struct test_data *data;
  52.         char msg[50];
  53.         int len;
  54. };

  55. static int test_remove(struct platform_device *pdev);

  56. static const u8 seg_table[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};

  57. static int test_open(struct inode *inode, struct file *file)
  58. {
  59.         struct test_file *p;
  60.        
  61.         p = kzalloc(sizeof(struct test_file), GFP_KERNEL);
  62.         if (p == NULL)
  63.                 return -ENOMEM;
  64.         file->private_data = p;
  65.        
  66.         p->data = container_of(inode->i_cdev, struct test_data, cdev);
  67.         snprintf(p->msg, sizeof(p->msg), "Number: %d\nCounter: %d\nGPT2->SR=0x%02x\n", p->data->number, readl(&p->data->GPT2->CNT), readl(&p->data->GPT2->SR));
  68.         p->len = strlen(p->msg);
  69.         return 0;
  70. }

  71. static int test_release(struct inode *inode, struct file *file)
  72. {
  73.         if (file->private_data != NULL)
  74.                 kfree(file->private_data);
  75.         return 0;
  76. }

  77. static ssize_t test_read(struct file *file, char __user *buf, size_t size, loff_t *off)
  78. {
  79.         int ret;
  80.         struct test_file *p = file->private_data;
  81.        
  82.         if (*off + size > p->len)
  83.                 size = p->len - *off;
  84.         if (size > 0)
  85.         {
  86.                 ret = copy_to_user(buf, p->msg, size);
  87.                 if (ret != 0)
  88.                         return -EFAULT;
  89.                 *off += size;
  90.         }
  91.         return size;
  92. }

  93. static ssize_t test_write(struct file *file, const char __user *buf, size_t size, loff_t *off)
  94. {
  95.         char ch;
  96.         char *s;
  97.         int ret;
  98.         struct test_file *p = file->private_data;
  99.        
  100.         if (size == 0)
  101.                 return -EFAULT;
  102.         get_user(ch, &buf[size - 1]);
  103.         if (ch != '\r' && ch != '\n')
  104.                 return -EFAULT;
  105.        
  106.         s = kzalloc(size, GFP_KERNEL);
  107.         if (s == NULL)
  108.                 return -ENOMEM;
  109.         ret = copy_from_user(s, buf, size - 1);
  110.         if (ret != 0)
  111.         {
  112.                 kfree(s);
  113.                 return -EFAULT;
  114.         }
  115.        
  116.         p->data->number = simple_strtol(s, NULL, 10);
  117.         if (p->data->number < 0)
  118.                 p->data->number = 0;
  119.         else if (p->data->number > 99999999)
  120.                 p->data->number = 99999999;
  121.         kfree(s);
  122.         return size;
  123. }

  124. static long test_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  125. {
  126.         return 0;
  127. }

  128. static const struct file_operations test_fops = {
  129.         .owner = THIS_MODULE,
  130.         .open = test_open,
  131.         .release = test_release,
  132.         .read = test_read,
  133.         .write = test_write,
  134.         .unlocked_ioctl = test_unlocked_ioctl
  135. };

  136. static void ser_in(struct test_data *p, u8 data)
  137. {
  138.         int i;
  139.        
  140.         for (i = 0; i < 8; i++)
  141.         {
  142.                 gpiod_set_value(p->gpios->desc[0], 0);
  143.                 if (data & 0x80)
  144.                         gpiod_set_value(p->gpios->desc[2], 1);
  145.                 else
  146.                         gpiod_set_value(p->gpios->desc[2], 0);
  147.                 gpiod_set_value(p->gpios->desc[0], 1);
  148.                 data <<= 1;
  149.         }
  150. }

  151. static void par_out(struct test_data *p)
  152. {
  153.         gpiod_set_value(p->gpios->desc[1], 0);
  154.         gpiod_set_value(p->gpios->desc[1], 1);
  155. }

  156. static irqreturn_t gpt2_irqhandler(int irq, void *dev)
  157. {
  158.         struct test_data *p = dev;
  159.        
  160.         // 74HC595扫描数码管
  161.         if (p->number_bit == 0)
  162.                 p->number_tmp = p->number;
  163.         else
  164.                 p->number_tmp /= 10;
  165.         ser_in(p, seg_table[p->number_tmp % 10]);
  166.         ser_in(p, 1 << p->number_bit);
  167.         par_out(p);
  168.        
  169.         p->number_bit++;
  170.         if (p->number_bit == 8)
  171.                 p->number_bit = 0;
  172.                
  173.         writel(GPT_SR_OF1, &p->GPT2->SR); // 写1清除中断
  174.         return IRQ_HANDLED;
  175. }

  176. static int test_probe(struct platform_device *pdev)
  177. {
  178.         int ret;
  179.         struct device_node *node;
  180.         struct resource res;
  181.         struct test_data *data;
  182.        
  183.         /* 创建结构体 */
  184.         pr_err("test_probe(0x%p);\n", pdev);
  185.         data = devm_kzalloc(&pdev->dev, sizeof(struct test_data), GFP_KERNEL);
  186.         if (data == NULL)
  187.         {
  188.                 pr_err("devm_kzalloc() failed\n");
  189.                 return -ENOMEM;
  190.         }
  191.         platform_set_drvdata(pdev, data);
  192.        
  193.         /* 创建设备 */
  194.         ret = alloc_chrdev_region(&data->devid, 100, 1, "mydeviceid");
  195.         if (ret != 0)
  196.         {
  197.                 pr_err("alloc_chrdev_region() failed\n");
  198.                 return ret;
  199.         }
  200.         pr_err("Device ID: %d,%d\n", MAJOR(data->devid), MINOR(data->devid));
  201.         cdev_init(&data->cdev, &test_fops);
  202.         ret = cdev_add(&data->cdev, data->devid, 1);
  203.         if (ret != 0)
  204.         {
  205.                 pr_err("cdev_add() failed\n");
  206.                 goto err;
  207.         }
  208.        
  209.         /* 创建设备文件 */
  210.         data->class = class_create(THIS_MODULE, "classname");
  211.         if (IS_ERR(data->class))
  212.         {
  213.                 pr_err("class_create() failed\n");
  214.                 ret = PTR_ERR(data->class);
  215.                 goto err;
  216.         }
  217.         data->device = device_create(data->class, NULL, data->devid, NULL, "devicename");
  218.         if (IS_ERR(data->device))
  219.         {
  220.                 pr_err("device_create() failed\n");
  221.                 ret = PTR_ERR(data->device);
  222.                 goto err;
  223.         }
  224.        
  225.         /* 获取GPIO端口 */
  226.         data->gpios = devm_gpiod_get_array(&pdev->dev, NULL, GPIOD_OUT_LOW);
  227.         if (IS_ERR(data->gpios))
  228.         {
  229.                 pr_err("devm_gpiod_get_array() failed\n");
  230.                 ret = PTR_ERR(data->gpios);
  231.                 goto err;
  232.         }
  233.        
  234.         /* 配置GPT2定时器 */
  235.         data->number = 20220605; // 数码管默认显示的数字
  236.         data->GPT2 = ioremap(0x020e8000, sizeof(struct imx6ull_gpt)); // 映射GPT2外设的寄存器
  237.         data->CCGR = ioremap(0x020c4068, sizeof(*data->CCGR)); // 映射CCM外设的CCGR0~1寄存器
  238.         if (data->GPT2 == NULL || data->CCGR == NULL)
  239.         {
  240.                 // 寄存器映射失败
  241.                 pr_err("ioremap() failed\n");
  242.                 ret = -EFAULT;
  243.                 goto err;
  244.         }
  245.         writel(readl(&data->CCGR[0]) | _BV(24), &data->CCGR[0]); // 在CCM中使能GPT2的时钟: gpt2_bus_clk_enable=1
  246.         pr_err("CCGR0=0x%08x\n", readl(&data->CCGR[0]));
  247.         pr_err("CCGR1=0x%08x\n", readl(&data->CCGR[1]));
  248.         pr_err("GPT2->CR=0x%08x\n", readl(&data->GPT2->CR));
  249.        
  250.         writel(GPT_IR_OF1IE, &data->GPT2->IR); // 开中断
  251.         pr_err("GPT2->IR=0x%02x\n", readl(&data->GPT2->IR));
  252.         pr_err("GPT2->SR=0x%02x\n", readl(&data->GPT2->SR));
  253.        
  254.         // 循环遍历设备树中所有指定compatible的节点
  255.         // node使用完毕后必须调用of_find_compatible_node或of_node_put释放掉
  256.         node = NULL;
  257.         while ((node = of_find_compatible_node(node, NULL, "fsl,imx6ul-gpt")) != NULL)
  258.         {
  259.                 ret = of_address_to_resource(node, 0, &res);
  260.                 pr_err("name=%s, full_name=%s, start=0x%08x\n", node->name, node->full_name, res.start);
  261.                 if (ret == 0 && res.start == 0x020e8000)
  262.                 {
  263.                         // 已找到gpt2节点
  264.                         data->irq = irq_of_parse_and_map(node, 0); // 解析interrupts属性, 得到linux中断号
  265.                         pr_err("found gpt2 node: irq=%d\n", data->irq);
  266.                         of_node_put(node);
  267.                         break;
  268.                 }
  269.         }
  270.         if (data->irq == 0)
  271.         {
  272.                 // 没有找到gpt2节点, 或者解析gpt2节点的interrupts属性失败
  273.                 pr_err("no IRQ found\n");
  274.                 ret = -ENODEV;
  275.                 goto err;
  276.         }
  277.         // 请求中断
  278.         ret = devm_request_irq(&pdev->dev, data->irq, gpt2_irqhandler, IRQF_TRIGGER_RISING, "gpt2_int", data);
  279.         if (ret != 0)
  280.         {
  281.                 pr_err("request_irq() failed! ret=%d\n", ret);
  282.                 goto err;
  283.         }
  284.        
  285.         writel(999, &data->GPT2->OCR1); // 计数最大值
  286.         writel(249, &data->GPT2->PR); // 分频系数
  287.         writel(GPT_SR_OF1, &data->GPT2->SR); // 打开定时器前必须清除中断, 以免中断线一直为高, 没有边沿出现, 无法进入中断函数
  288.         writel((1 << GPT_CR_CLKSRC_Pos) | GPT_CR_EN, &data->GPT2->CR); // 开始定时
  289.         pr_err("GPT2->CR=0x%08x\n", readl(&data->GPT2->CR));
  290.         return 0;
  291.        
  292. err:
  293.         test_remove(pdev);
  294.         return ret;
  295. }

  296. static int test_remove(struct platform_device *pdev)
  297. {
  298.         struct test_data *data;
  299.        
  300.         pr_err("test_remove(0x%p);\n", pdev);
  301.         data = platform_get_drvdata(pdev);
  302.         if (data != NULL)
  303.         {
  304.                 if (data->GPT2 != NULL)
  305.                 {
  306.                         pr_err("GPT2->CR=0x%08x\n", readl(&data->GPT2->CR));
  307.                         writel(readl(&data->GPT2->CR) & ~GPT_CR_EN, &data->GPT2->CR); // 停止定时
  308.                         pr_err("GPT2->CR=0x%08x\n", readl(&data->GPT2->CR));
  309.                         iounmap(data->GPT2);
  310.                 }
  311.                 if (data->CCGR != NULL)
  312.                         iounmap(data->CCGR);
  313.                 if (data->device != NULL && !IS_ERR(data->device))
  314.                         device_destroy(data->class, data->devid);
  315.                 if (data->class != NULL && !IS_ERR(data->class))
  316.                         class_destroy(data->class);
  317.                 cdev_del(&data->cdev);
  318.                 unregister_chrdev_region(data->devid, 1);
  319.                 platform_set_drvdata(pdev, NULL);
  320.         }
  321.         return 0;
  322. }

  323. static const struct of_device_id test_match_ids[] = {
  324.         {.compatible = "mygpiotest,myboard2"},
  325.         {}
  326. };

  327. MODULE_DEVICE_TABLE(of, test_match_ids);

  328. static struct platform_driver test_driver = {
  329.         .driver = {
  330.                 .name = "mytestdriver",
  331.                 .of_match_table = of_match_ptr(test_match_ids)
  332.         },
  333.         .probe = test_probe,
  334.         .remove = test_remove
  335. };

  336. module_platform_driver(test_driver);

  337. MODULE_AUTHOR("Oct1158");
  338. MODULE_LICENSE("GPL");
复制代码
回复

使用道具 举报

1

主题

15

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2017-9-27
在线时间
6 小时
 楼主| 发表于 2022-6-19 13:02:05 | 显示全部楼层
本帖最后由 zlk1214 于 2022-6-19 13:41 编辑

设备树代码:
(说明:要想使设备树中的pinctrl-*属性生效,这个节点的compatible属性就必须要匹配上某个驱动。所以驱动程序必须写成platform_driver的形式,不能光是module_init,这个在正点原子的教程里面没有说)
  1. #include "imx6ull-14x14-emmc-4.3-800x480-c.dts"

  2. / {
  3.         mygpiotest {
  4.                 compatible = "mygpiotest,myboard2";
  5.                 pinctrl-names = "default";
  6.                 pinctrl-0 = <&pinctrl_mygpiotest>;
  7.                 gpios = <&gpio4 26 GPIO_ACTIVE_HIGH /* 引脚名: CSI_DATA05, 板上丝印: CAMERA D5  */
  8.                          &gpio4 25 GPIO_ACTIVE_HIGH /* 引脚名: CSI_DATA04, 板上丝印: CAMERA D4 */
  9.                                  &gpio4 28 GPIO_ACTIVE_HIGH /* 引脚名: CSI_DATA07, 板上丝印: CAMERA D7 */
  10.                                  &gpio4 27 GPIO_ACTIVE_HIGH /* 引脚名: CSI_DATA06, 板上丝印: CAMERA D6 */
  11.                 >;
  12.         };
  13. };

  14. &iomuxc {
  15.         imx6ul-evk {
  16.                 /delete-node/csi1grp;
  17.                
  18.                 pinctrl_mygpiotest: mygpiotestgrp {
  19.                         fsl,pins = <
  20.                                 MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x10b0 /* 引脚名为CSI_DATA05的引脚复用为GPIO4_IO26 */
  21.                                 MX6UL_PAD_CSI_DATA04__GPIO4_IO25 0x10b0
  22.                                 MX6UL_PAD_CSI_DATA07__GPIO4_IO28 0x10b0
  23.                                 MX6UL_PAD_CSI_DATA06__GPIO4_IO27 0x10b0
  24.                         >;
  25.                 };
  26.         };
  27. };

  28. /* 删除不需要的节点 */
  29. &i2c2 {
  30.         /delete-node/ov5640@3c;
  31. };
  32. &csi {
  33.         status = "disabled";
  34.         /delete-node/port;
  35. };
复制代码
回复

使用道具 举报

1

主题

15

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2017-9-27
在线时间
6 小时
 楼主| 发表于 2022-6-19 13:02:44 | 显示全部楼层
本帖最后由 zlk1214 于 2022-6-19 13:51 编辑

冒泡排序C程序代码:
  1. #include <stdlib.h>

  2. #define N 10000

  3. static void sort(void)
  4. {
  5.         int arr[N];
  6.         int i, j, temp;
  7.         
  8.         for (i = 0; i < N; i++)
  9.                 arr[i] = rand();
  10.         for (i = 0; i < N - 1; i++)
  11.         {
  12.                 for (j = 0; j < N - i - 1; j++)
  13.                 {
  14.                         if (arr[j] > arr[j + 1])
  15.                         {
  16.                                 temp = arr[j];
  17.                                 arr[j] = arr[j + 1];
  18.                                 arr[j + 1] = temp;
  19.                         }
  20.                 }
  21.         }
  22. }

  23. int main(void)
  24. {
  25.         while (1)
  26.                 sort();
  27.         return 0;
  28. }
复制代码


查看寄存器的值的程序:
  1. #include <asm/io.h>
  2. #include <linux/module.h>

  3. static int __init cv_init(void)
  4. {
  5.         u32 temp, value;
  6.         void __iomem *CCM_CBCMR;
  7.         void __iomem *CCM_CBCDR;
  8.         void __iomem *CCM_CSCMR1;
  9.         void __iomem *CCM_CMEOR;
  10.        
  11.         CCM_CBCDR = ioremap(0x020c4014, 4);
  12.         value = readl(CCM_CBCDR);
  13.         iounmap(CCM_CBCDR);
  14.         pr_err("CCM_CBCDR=0x%08x\n", value);
  15.         temp = (value >> 8) & 3;
  16.         pr_err("  [IPG_PODF]=%d (divide by %d)\n", temp, temp + 1);
  17.         temp = (value >> 10) & 7;
  18.         pr_err("  [AHB_PODF]=%d (divide by %d)\n", temp, temp + 1);
  19.         temp = (value >> 26) & 1;
  20.         pr_err("  [GLITCHLESS MUX]=[PERIPH_CLK_SEL]|[PLL_BYPASS_EN2]=%d|0=%d\n", temp, temp);
  21.        
  22.         CCM_CBCMR = ioremap(0x020c4018, 4);
  23.         value = readl(CCM_CBCMR);
  24.         iounmap(CCM_CBCMR);
  25.         pr_err("CCM_CBCMR=0x%08x\n", value);
  26.         temp = (value >> 18) & 2;
  27.         pr_err("  [PRE_PERIPH_CLK_SEL]=%d\n", temp);
  28.        
  29.         CCM_CSCMR1 = ioremap(0x020c401c, 4);
  30.         value = readl(CCM_CSCMR1);
  31.         iounmap(CCM_CSCMR1);
  32.         pr_err("CCM_CSCMR1=0x%08x\n", value);
  33.         temp = value & 0x3f;
  34.         pr_err("  [PERCLK_PODF]=%d (divide by %d)\n", temp, temp + 1);
  35.        
  36.         CCM_CMEOR = ioremap(0x020c4088, 4);
  37.         value = readl(CCM_CMEOR);
  38.         iounmap(CCM_CMEOR);
  39.         pr_err("CCM_CMEOR=0x%08x\n", value);
  40.         temp = (value >> 5) & 1;
  41.         pr_err("  [MOD_EN_OV_GPT]=%d\n", temp);
  42.        
  43.         return -ENODEV;
  44. }

  45. static void __exit cv_exit(void)
  46. {
  47. }

  48. module_init(cv_init);
  49. module_exit(cv_exit);
  50. MODULE_AUTHOR("Oct1158");
  51. MODULE_LICENSE("GPL");
复制代码
回复

使用道具 举报

1

主题

15

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2017-9-27
在线时间
6 小时
 楼主| 发表于 2022-6-19 13:06:08 | 显示全部楼层
Untitled.png
回复

使用道具 举报

1

主题

15

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2017-9-27
在线时间
6 小时
 楼主| 发表于 2022-6-19 13:15:15 | 显示全部楼层
驱动中GPT2->PR改成24,同时在linux系统里面运行冒泡排序的C程序,数码管才能完整显示8个数字,且各数位不闪烁。
冒泡排序的程序一旦退出,数码管数位扫描就很慢了,七八秒才扫描完一遍。
3.png
回复

使用道具 举报

1

主题

15

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2017-9-27
在线时间
6 小时
 楼主| 发表于 2022-6-19 13:25:44 | 显示全部楼层
Untitled.png
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-5-14 17:51

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表