Prechádzať zdrojové kódy

修复数码管bug:1、驱动支持客户要求的格式数据。2、提供客户要求格式的测试程序。

qidong.liu 1 mesiac pred
rodič
commit
b98f2a0ceb
3 zmenil súbory, kde vykonal 188 pridanie a 175 odobranie
  1. 8 6
      Makefile
  2. 34 5
      ssegment.c
  3. 146 164
      test_app/setss.c

+ 8 - 6
Makefile

@@ -5,22 +5,24 @@ obj-m := opal.o
 
 opal-objs := main.o led.o light_ring.o ssegment.o ec_version.o buzzer.o fan.o writeprotect.o myname.o cash_drawers.o batteryled.o watchdog.o power.o switches.o backlight.o gsensor.o lcd_2x20.o smart_battery.o
 
-
+PROJECT_NAME := POS
 KERNELDIR := ~/timesys/SDK64Bit-V6_02_00/kernel-source/linux-5.15/
-ccflags-y += -I./include
+ccflags-y += -I./include -DPROJECT=$(PROJECT_NAME)
 EXTRA_CFLAGS +=-g -I$(PWD)/include
 
 INSTALL_DIR := /lib/modules/$(shell uname -r)/extra
- 
+
 PWD = $(shell pwd)
 all:
 	make CROSS_COMPILE=~/timesys/SDK64Bit-V6_02_00/toolchain/bin/x86_64-timesys-linux-gnu- -C $(KERNELDIR) M=$(PWD) modules
+	~/timesys/SDK64Bit-V6_02_00/toolchain/bin/x86_64-timesys-linux-gnu-gcc test_app/setss.c -DPROJECT=$(PROJECT_NAME) -o test_app/setss
+
 clean:
-	rm -rf *.o
-	rm *.ko *.order *.mod.c *.symvers \.*\.o\.cmd
+	rm -rf *.o test_app/setss
+	rm -rf *.ko *.order *.mod.c *.symvers \.*\.cmd
 
 module_install:
 	@echo "Installing $(MODULE_NAME).ko to $(INSTALL_DIR)"
 	@sudo mkdir -p $(INSTALL_DIR)
 	@sudo cp $(MODULE_NAME).ko $(INSTALL_DIR)/
-	@echo "Module installed successfully"
+	@echo "Module installed successfully"

+ 34 - 5
ssegment.c

@@ -14,10 +14,14 @@
 #include <linux/io.h>
 #include "gpioregs.h"
 
+#if defined(PROJECT) && (PROJECT == POS)
+#define DEVICE_NAME "leds"
+#else
 #define DEVICE_NAME "ssegment"
+#endif
 #define CLASS_NAME "ssegment_class"
 #define DRIVER_NAME     "port80_seg7"
-#define BUFFER_SIZE 1024
+#define BUFFER_SIZE 4
 
 static int major = 56; 
 static int minor = 40; 
@@ -33,7 +37,7 @@ static dev_t dev_num;
 
 struct ssegment_dev
 {
-    char *buffer;
+    unsigned char *buffer;
     size_t size;
     struct mutex lock;
     struct cdev cdev;
@@ -62,9 +66,11 @@ static void delay_work_func(struct work_struct *work)
 {
     int ret = 0;
     unsigned int val = 0;
+    unsigned char display_value = 0;
+    static unsigned int flag = 0;
     if(dev->size != 0)
     {
-        outb(dev->buffer[0], PORT_80);
+        // outb(dev->buffer[0], PORT_80);
         if((dev->buffer[1] & 0x02))
         {
             val = readl_cust(SSEGMENT_POINT);
@@ -80,13 +86,25 @@ static void delay_work_func(struct work_struct *work)
 
         if((dev->buffer[1] & 0x80))
         {
+            flag++;
+            if(flag % 2 == 1)
+            {
+                display_value = dev->buffer[0];
+            }
+            else
+            {
+                display_value = 0;
+            }
+            schedule_delayed_work(&dev->delay_work1, msecs_to_jiffies(1000));
         }
         else
         {
+            flag = 0;
+            display_value = dev->buffer[0];
         }
-    }
-
 
+        outb(display_value, PORT_80);
+    }
     
     printk(KERN_INFO "delay_work_func\n");
 }
@@ -175,6 +193,8 @@ static ssize_t ssegment_write(struct file *filp, const char __user *buf,
         goto out;
     }
 
+    printk("%02x %02x %02x %02x\n", dev->buffer[0], dev->buffer[1], dev->buffer[2], dev->buffer[3]);
+
     dev->size = count;
 
     printk(KERN_INFO "ssegment: Written %zu bytes\n", count);
@@ -197,6 +217,13 @@ static struct file_operations fops = {
     .write = ssegment_write,
 };
 
+static char *my_devnode(struct device *dev, umode_t *mode) {
+    if (mode) {
+        *mode = 0666;
+    }
+    return NULL;
+}
+
 int ssegment_init(void)
 {
     int result;
@@ -260,6 +287,8 @@ int ssegment_init(void)
         goto fail_class;
     }
 
+    char_class->devnode = my_devnode;
+
     char_device = device_create(char_class, NULL, dev_num, NULL, DEVICE_NAME);
     if (IS_ERR(char_device))
     {

+ 146 - 164
test_app/setss.c

@@ -1,196 +1,178 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <fcntl.h>
 #include <unistd.h>
+#include <errno.h>
 #include <getopt.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 
-//7-segment digital tube
-typedef struct {
-    char *f_arg;     
-    int r_flag;      
-    int d_flag;      
-    char *str_arg;   
-} Options;
-
-int flash_flag = 0;
-int read_flag = 0;
-int dp_flag = 0;
-long int display_value = 0;
-
-void print_usage(const char *program_name) {
-    printf("Usage: %s [options] <string>\n", program_name);
-    printf("Options:\n");
-    printf("  -f <arg>    Specify an argument for -f option\n");
-    printf("  -r          Enable r option (no argument)\n");
-    printf("  -d          Enable d option (no argument)\n");
-    printf("  -h          Show this help message\n");
-    printf("\nExample:\n");
-    printf("  %s -f config.txt -r -d hello\n", program_name);
-    printf("  %s -r -f data.txt world\n", program_name);
-}
+#if defined(PROJECT) && (PROJECT == POS)
+#define DEVICE_PATH "/dev/leds"
+#else
+#define DEVICE_PATH "/dev/ssegment"
+#endif
 
-int parse_arguments(int argc, char *argv[], Options *opts) {
-    int opt;
-    int ret = 0;
-    int f_option_count = 0; 
-    
-    memset(opts, 0, sizeof(Options));
-    
-    while ((opt = getopt(argc, argv, "f:rdh")) != -1) {
-        switch (opt) {
-            case 'f':
-                flash_flag = atoi(optarg);
-                opts->f_arg = optarg;
-                f_option_count++;
-                printf("[DEBUG] -f option with argument: %s\n", optarg);
-                break;
-                
-            case 'r':
-                read_flag = 1;
-                opts->r_flag = 1;
-                printf("[DEBUG] -r option enabled\n");
-                break;
-                
-            case 'd':
-                dp_flag = 1;
-                opts->d_flag = 1;
-                printf("[DEBUG] -d option enabled\n");
-                break;
-                
-            case 'h':
-                print_usage(argv[0]);
-                return 0; 
-                
-            case '?':
-                return -1;
-                
-            default:
-                fprintf(stderr, "Unexpected option: %c\n", opt);
-                return -1;
-        }
-    }
-    
-    if (f_option_count > 1) {
-        fprintf(stderr, "Error: -f option can only be used once\n");
-        return -1;
+
+int write_data_to_device(unsigned int data)
+{
+    int fd;
+    ssize_t ret;
+
+    // 打开设备
+    fd = open(DEVICE_PATH, O_WRONLY);
+    if (fd < 0)
+    {
+        return 1;
     }
-    
-    if (optind < argc) {
-        if (argc - optind > 1) {
-            fprintf(stderr, "Warning: Extra arguments after string will be ignored\n");
-        }
-        opts->str_arg = argv[optind];
-        char *endptr;
-        display_value = strtol(opts->str_arg, &endptr, 16);
-        if(*endptr != '\0')
-        {
-            printf("Error: Invalid string argument\n");
-            return -1;
-        }
-        else
-        {
-            printf("display_value=%lx\n", display_value);
-        }
 
-        printf("[DEBUG] String argument: %s\n", opts->str_arg);
-    } else {
-        fprintf(stderr, "Error: Missing required string argument\n");
-        print_usage(argv[0]);
-        return -1;
+    // 写入1字节
+    ret = write(fd, &data, sizeof(data));
+    if (ret < 0)
+    {
+        close(fd);
+        return 1;
     }
-    
-    return 1;
+    close(fd);
+    return 0;
 }
 
-void show_results(Options *opts) {
-    printf("\n=== Parsing Results ===\n");
-    
-    if (opts->f_arg) {
-        printf("-f option argument: %s\n", opts->f_arg);
-    } else {
-        printf("-f option not specified\n");
+int read_from_device(unsigned int *data)
+{
+    int fd;
+    unsigned char buffer[256];
+    ssize_t ret;
+    int i;
+
+    fd = open(DEVICE_PATH, O_RDWR);
+    if (fd < 0)
+    {
+        return 1;
     }
-    
-    printf("-r option: %s\n", opts->r_flag ? "enabled" : "disabled");
-    printf("-d option: %s\n", opts->d_flag ? "enabled" : "disabled");
-    
-    if (opts->str_arg) {
-        printf("String argument: %s\n", opts->str_arg);
+
+    ret = read(fd, data, sizeof(unsigned int));
+    if (ret < 0)
+    {
+        return 1;
     }
-    
-    printf("======================\n");
+
+    close(fd);
+    return 0;
 }
 
-int main(int argc, char *argv[]) {
-    Options opts;
-    int ret;
-    unsigned int cmd = 0;
-    int fd = 0;
-    
-    printf("Argument Parser Demo\n");
-    printf("====================\n");
-    printf("Total arguments: %d\n", argc);
-    
-
-    printf("Raw arguments:");
-    for (int i = 0; i < argc; i++) {
-        printf(" [%d]%s", i, argv[i]);
-    }
-    printf("\n\n");
-    
-    ret = parse_arguments(argc, argv, &opts);
-    
-    if (ret == 0) {
-        return 0;
-    } else if (ret < 0) {
-        fprintf(stderr, "\nArgument parsing failed!\n");
+
+int main(int argc, char *argv[])
+{
+    int ret = 0;
+    int opt;
+    int flash_option = 0;
+    int flash_value = 0;
+    int decimal_point = 0;
+    int read_option = 0;
+    char *hex_arg = NULL;
+    unsigned char data;
+    unsigned int rw_data = 0;
+
+    // 如果没有参数,显示帮助
+    if (argc == 1)
+    {
         return 1;
     }
-    
-    show_results(&opts);
-    fd = open("/dev/ssegment", O_RDWR);
-    if(fd < 0)
+
+    // 解析命令行参数
+    optind = 1; // 重置 getopt
+    while ((opt = getopt(argc, argv, "f:dr")) != -1)
     {
-        printf("open led device failed\n");
-        return -1;
+        switch (opt)
+        {
+        case 'f':
+            flash_option = 1;
+            flash_value = atoi(optarg);
+            if (flash_value <= 0)
+            {
+                fprintf(stderr, "错误: -f 参数必须是大于0的数字\n");
+                return 1;
+            }
+            break;
+        case 'd':
+            decimal_point = 1;
+            break;
+        case 'r':
+            read_option = 1;
+            break;
+        default:
+            printf("error\n");
+            return 1;
+        }
+    }
+
+    // 检查 -r 选项的特殊规则
+    if (read_option)
+    {
+        rw_data = 0;
+        ret = read_from_device(&rw_data);
+        data = rw_data & 0xFF;
+        printf("The number displayed is %02x\n", data);
+        if(rw_data & (1<<9))
+        {
+            printf("The msb is ON\n");
+        }
+        else
+        {
+            printf("The msb is OFF\n");
+        }
+        if(rw_data & (1<<15))
+        {
+            printf("The flashing is ON\n");
+        }
+        else
+        {
+            printf("The flashing is OFF\n");
+        }
+        return 0;
     }
-    
-    cmd = 0;
-    if(dp_flag == 1)
+
+    // 非 -r 选项,必须有最后的十六进制参数
+    if (optind >= argc)
     {
-        cmd = cmd | 0x0200;
+        fprintf(stderr, "error\n");
+        return 1;
     }
-    if(flash_flag == 1)
+
+    hex_arg = argv[optind];
+
+    // 解析十六进制参数 (支持 aa, bb, 12 等格式)
+    char *endptr;
+    long hex_value = strtol(hex_arg, &endptr, 16);
+
+    // 检查转换是否成功
+    if (*endptr != '\0' || endptr == hex_arg)
     {
-        cmd = cmd | 0x8000;
+        fprintf(stderr, "错误: 无效的十六进制参数 '%s'\n", hex_arg);
+        fprintf(stderr, "请使用类似 aa, bb, 12, 0x12 的格式\n");
+        return 1;
     }
 
-    cmd = cmd | (display_value & 0xff);
-    if(read_flag == 1)
+    // 检查范围 (0-255)
+    if (hex_value < 0 || hex_value > 255)
     {
-        cmd = 0;
-        ret = read(fd, &cmd, 4);
-        if(ret < 0)
-        {
-            printf("read led device failed\n");
-            return -1;
-        }
-        printf("read led device success, cmd=%x\n", cmd);
+        fprintf(stderr, "错误: 十六进制值必须在 0x00-0xFF 之间 (当前: 0x%lX)\n", hex_value);
+        return 1;
     }
-    else
+
+    data = (unsigned char)hex_value;
+
+
+    if (flash_value == 1)
     {
-        ret = write(fd, &cmd, 4);
-        if(ret < 0)
-        {
-            printf("write led device failed\n");
-            return -1;
-        }
+        rw_data |= 1 << 15;
     }
 
+    if (decimal_point == 1)
+    {
+        rw_data |= 1 << 9;
+    }
 
-    
+    rw_data |= data;
+    ret = write_data_to_device(rw_data);
     return 0;
-}
+}