Hauptseite

Programmieren


Wegen meines Interessen ich programmiere in ASM, C und C++. Neben dessen kann ich auch in Visual Basic, HTML, SQL, JS, CSS, PHP programmieren.

Ich werde in dieser Abteilung Quellencode der einzelner Projekte anbringen.
Ich werde hier auch Programme gebunden mit den typischen programmatischen Aufgaben (keine Mikroprozessoraufgaben) manchmal anbringen.

Darunter präsentiere ich das Fragment des Codes des Kerneltreibers und die Anwendung welche diesen Treiber verwendet.

  • Definieren der Ressourcen des Treibers
  • Quellcode des GPIO Treibers für MCU STM32
  • die Anwendung welche operiert auf den I/O Anschlüssen

Definieren der Ressourcen des Treibers
(die Vollbildansicht)

static struct resource stm3210e_eval_gpios_resources[] = { [0] = { .start = 0, .end = 15, .flags = IORESOURCE_IRQ, }, [1] = { .start = 0, .end = 15, .flags = IORESOURCE_IRQ, }, }; static struct platform_device stm3210e_eval_gpios_device = { .name = "io-gpio", .id = -1, .num_resources = 2, .resource = stm3210e_eval_gpios_resources, };

Quellcode des GPIO Treibers für STM32
(die Vollbildansicht)

/* * Character driver for ARM STM32 chip GPIO port implemented * separately for inputs and outputs * * Copyright © 2013 Lukasz Kazmierczak */ #include ... #define DRIVER_NAME "io-gpio" #define PFX DRIVER_NAME ": " #define DRIVER_DEVICES_NB 2U #define MAX_GPIO_RANGE 16U static int initialize_gpio_inputs(void); static int initialize_gpio_outputs(void); struct gpio_data { atomic_t open_count; }; struct group_data { dev_t dev_node; struct cdev cdev; struct resource *gpio_range; struct gpio_data *gpios; }; typedef struct group_data group_data_struct; group_data_struct *group_data_vect[DRIVER_DEVICES_NB] = {0}; int initialize_gpio_inputs() { int i=0, ret=-1; for(i=0; i < MAX_GPIO_RANGE; i++) gpio_direction_input(i, 1); if(i == MAX_GPIO_RANGE) ret = 0; return ret; } int initialize_gpio_outputs() { int i=0, ret = -1; for(i=0; i < MAX_GPIO_RANGE; i++) { gpio_direction_output(i, 0); gpio_set_value(i, 0); } if(i == MAX_GPIO_RANGE) ret = 0; return ret; } /** * simple_gpio_read - readout pin status from input port * ex. $ cat /dev/gpioG8 */ static ssize_t simple_gpioin_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { unsigned int gpio = iminor(file->f_path.dentry->d_inode); static char *buf_signature = 0; ssize_t ret = 0; //printk("gpio read requested from input port: count %d, buf %p\n", count, buf); if(count > 1 && buf_signature == buf) { //second call for exceeding data readout, abort reading buf_signature = 0; count = 0; } else if(count > 1) { //first call for exceeding data readout, return available reading buf_signature = buf; count = 3; } else { //no action defined } char byte = '0'; gpio_direction_input(gpio, 1); byte += gpio_get_value(gpio); //printk("Input readout for pin: %d is %c\n", gpio, byte); ret = count; if(count > 2) { if (put_user(byte, buf) || put_user('\n', buf + 1) || put_user('\0', buf + 2)) ret = -1; } else if(count == 1){ if (put_user(byte, buf)) ret = -1; } else { //no action defined } return ret; } /** * simple_gpio_read - readout pin status from output port: no action * ex. $ cat /dev/gpioF8 */ static ssize_t simple_gpio_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { ssize_t ret = -1; printk("gpio read requested for output port: operation not supported\n"); return ret; } /** * simple_gpioin_write - set pin state of input port to desired value: no action * ex. $ echo '1' > /dev/gpioG8 */ static ssize_t simple_gpioin_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { ssize_t ret = -1; printk("write requested for input port: operation not supported!\n"); return ret; } /** * simple_gpio_write - set pin state of output port to desired value * ex. $ echo '1' > /dev/gpioF8 */ static ssize_t simple_gpio_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { unsigned int gpio = iminor(file->f_path.dentry->d_inode); ssize_t i = 0, ret = -1; char uvalue = 0; int value = 0; //printk("gpio write requested for output port: count %d, buf %p\n", count, buf); i = 0; while (i < count) { char byte = 0; int user_ret = get_user(byte, buf + i); i++; if (user_ret) return user_ret; switch (byte) { case '\r': case '\n': continue; case 'T': case '0': case '1': uvalue = byte; break; default: uvalue = 0; i = count; } GPIO_DBG("processed byte '%c'", byte); } if(uvalue != 0) { switch (uvalue) { case 'T': value = !gpio_get_output_value(gpio); break; default: value = uvalue - '0'; } gpio_direction_output(gpio, 0); gpio_set_value(gpio, value); ret = count; } return ret; } /** * simple_gpio_open - allocate specific pin of GPIO port to be accessed * */ static int simple_gpio_open(struct inode *ino, struct file *file) { struct group_data *group_data = container_of(ino->i_cdev, struct group_data, cdev); unsigned int gpio = iminor(ino); struct gpio_data *gpio_data = &group_data->gpios[gpio - group_data->gpio_range->start]; int ret; if (gpio < group_data->gpio_range->start || gpio > group_data->gpio_range->end) return -ENXIO; ret = gpio_request(gpio, DRIVER_NAME); if (ret) return ret; atomic_inc(&gpio_data->open_count); return 0; } /** * simple_gpio_close - deallocate specific pin of GPIO port from being accessed * */ static int simple_gpio_release(struct inode *ino, struct file *file) { struct group_data *group_data = container_of(ino->i_cdev, struct group_data, cdev); unsigned int gpio = iminor(ino); struct gpio_data *gpio_data = &group_data->gpios[gpio - group_data->gpio_range->start]; /* do not free until last consumer has closed */ if (atomic_dec_and_test(&gpio_data->open_count)) gpio_free(gpio); else GPIO_DBG("gpio still in use -- not freeing"); return 0; } static int simple_gpio_ioctl(struct inode * ino, struct file * file, unsigned int a, unsigned long b) { return 0; } static struct class *simple_gpio_class; /** * simple_gpio_fops - define operations for specific resource * */ static struct file_operations simple_gpio_fops[] = { [0] = { .owner = THIS_MODULE, .read = simple_gpio_read, .write = simple_gpio_write, .open = simple_gpio_open, .release = simple_gpio_release, .ioctl = simple_gpio_ioctl, }, [1] = { .owner = THIS_MODULE, .read = simple_gpioin_read, .write = simple_gpioin_write, .open = simple_gpio_open, .release = simple_gpio_release, .ioctl = simple_gpio_ioctl, }, }; /** * simple_gpio_probe - allocate resources and bind as character devices * */ static int __devinit simple_gpio_probe(struct platform_device *pdev) { int ret = 0, dev = 0; char *devName[][DRIVER_DEVICES_NB] = { { "gpio", "gpio%i" }, { "gpioin", "gpioin%i" }, }; group_data_struct *(*group_data_init)[DRIVER_DEVICES_NB] = kzalloc(sizeof(group_data_vect), GFP_KERNEL); platform_set_drvdata(pdev, group_data_init); while(dev < DRIVER_DEVICES_NB) { struct group_data *group_data; struct resource *gpio_range = platform_get_resource(pdev, IORESOURCE_IRQ, dev); int gpio, gpio_max = gpio_range->end - gpio_range->start + 1; group_data = kzalloc(sizeof(*group_data) + sizeof(struct gpio_data) * gpio_max, GFP_KERNEL); if (!group_data) return -ENOMEM; group_data->gpio_range = gpio_range; group_data->gpios = (void *)group_data + sizeof(*group_data); (*group_data_init)[dev] = group_data; ret = alloc_chrdev_region(&group_data->dev_node, gpio_range->start, gpio_max, devName[dev][0]); if (ret) { pr_devinit(KERN_ERR PFX "unable to get a char device\n"); kfree(group_data); return ret; } cdev_init(&group_data->cdev, &simple_gpio_fops[dev]); group_data->cdev.owner = THIS_MODULE; ret = cdev_add(&group_data->cdev, group_data->dev_node, gpio_max); if (ret) { pr_devinit(KERN_ERR PFX "unable to register char device\n"); unregister_chrdev_region(group_data->dev_node, gpio_max); kfree(group_data); return ret; } for (gpio = gpio_range->start; gpio <= gpio_range->end; ++gpio) { device_create(simple_gpio_class, &pdev->dev, group_data->dev_node + gpio, NULL, devName[dev][1], (int)gpio); } device_init_wakeup(&pdev->dev, 1); pr_devinit(KERN_INFO PFX "Dev %d: now handling %i GPIOs: %i - %i, registered as %d\n", dev+1, gpio_max, gpio_range->start, gpio_range->end, MAJOR(group_data->dev_node) ); dev++; } if(ret == 0) { //no error occured, no further action needed } else if(dev > 0) { //ToDo //initisalization of second resource failed //uninitialization has to be done for the first resource } else { //ToDo //first resorce initialization failed and is uninitialized //second resource is not to be initialized } return ret; } /** * simple_gpio_remove - remove character devices of GPIO resources. */ static int __devexit simple_gpio_remove(struct platform_device *pdev) { int ret = 0, dev = 0; group_data_struct *(*group_data_deinit)[DRIVER_DEVICES_NB]=platform_get_drvdata(pdev); while(dev < DRIVER_DEVICES_NB) { struct group_data *group_data = (*group_data_deinit)[dev]; struct resource *gpio_range = group_data->gpio_range; int gpio=0, gpio_max=gpio_range->end - gpio_range->start + 1; for (gpio = gpio_range->start; gpio <= gpio_range->end; ++gpio) device_destroy(simple_gpio_class, group_data->dev_node + gpio); cdev_del(&group_data->cdev); unregister_chrdev_region(group_data->dev_node, gpio_max); kfree(group_data); dev++; } kfree(group_data_deinit); return ret; } struct platform_driver simple_gpio_device_driver = { .probe = simple_gpio_probe, .remove = __devexit_p(simple_gpio_remove), .driver = { .name = DRIVER_NAME, } }; /** * simple_gpio_init - initial startup of GPIO driver * */ static int __init simple_gpio_init(void) { //initialize_gpio_inputs(); //initialize_gpio_outputs(); simple_gpio_class = class_create(THIS_MODULE, DRIVER_NAME); if (IS_ERR(simple_gpio_class)) { pr_init(KERN_ERR PFX "unable to create gpio class\n"); return PTR_ERR(simple_gpio_class); } return platform_driver_register(&simple_gpio_device_driver); } module_init(simple_gpio_init); /** * simple_gpio_exit - dropping GPIO device driver */ static void __exit simple_gpio_exit(void) { class_destroy(simple_gpio_class); platform_driver_unregister(&simple_gpio_device_driver); } module_exit(simple_gpio_exit); MODULE_AUTHOR("Lukasz Kazmierczak"); MODULE_DESCRIPTION("STM32 input/output port driver"); MODULE_LICENSE("GPL");

die Anwendung welche operiert auf den I/O Anschlüssen
(die Vollbildansicht)

/******************************************************************************* * keyboard-LED control application * Copyright © 2013 Lukasz Kazmierczak *******************************************************************************/ #include ... #define KBD_BUTTONS 5U #define LEDS 4U #define LED_UP 1U #define LED_DOWN 2U #define LED_LEFT 0U #define LED_RIGHT 3U #define KBD_SEL 0U #define KBD_UP 2U #define KBD_DOWN 1U #define KBD_LEFT 3U #define KBD_RIGHT 4U unsigned char _term=0; static void signal_handler(int signal) { if(signal == SIGTERM) { printf("Termination signal received\n"); _term = 1; } else { // unsupported signal } } int main(int argc, char ** argv) { int LED[LEDS]={0}, KBD[KBD_BUTTONS]={0}; int ret = -1, i = 0; int kbdChkMsDelay = 100; struct timespec req = { .tv_sec=0, .tv_nsec= kbdChkMsDelay * 1000000 }; char *LED_gpio[] = { "/dev/gpioF6", "/dev/gpioF7", "/dev/gpioF8", "/dev/gpioF9" }; char *KBD_gpio[] = { "/dev/gpioG7", "/dev/gpioG8", "/dev/gpioG11", "/dev/gpioG13", "/dev/gpioG14" }; if(argc != 1) { printf("%s.\n"\ "\tapplication sets LEDs depend of JOY buttons state\n"\ "\tsignal (\"kill -TERM \") kills the application\n", argv[0]); ret = 0; } else { signal(SIGTERM, signal_handler); for(i = 0; i < LEDS; i++) LED[i] = open(LED_gpio[i], O_WRONLY); for(i = 0; i < KBD_BUTTONS; i++) KBD[i] = open(KBD_gpio[i], O_RDONLY); if(LED[0]<0||LED[1]<0||LED[2]<0||LED[3]<0) { printf("can not open gpio port for writing.\n"); return ret; } if(KBD[0]<0||KBD[1]<0||KBD[2]<0||KBD[3]<0||KBD[4]<0) { printf("can not open gpio port for reading.\n"); return ret; } for(i = 0; i < LEDS; i++) write(LED[i], "0", 1); while(_term == 0) { for (i=0; i< KBD_BUTTONS; i++) { char buttonState = 0; read(KBD[i], &buttonState, 1); buttonState = '0' + (!(buttonState - '0')); // mapping buttons to LEDs switch(i) { case KBD_UP: write(LED[LED_UP], &buttonState, 1); break; case KBD_DOWN: write(LED[LED_DOWN], &buttonState, 1); break; case KBD_LEFT: write(LED[LED_LEFT], &buttonState, 1); break; case KBD_RIGHT: write(LED[LED_RIGHT], &buttonState, 1); break; case KBD_SEL: write(LED[LED_UP], &buttonState, 1); write(LED[LED_DOWN], &buttonState, 1); write(LED[LED_LEFT], &buttonState, 1); write(LED[LED_RIGHT], &buttonState, 1); break; default: { /* button not supported */ } } } nanosleep(&req, NULL); } for(i = 0; i < LEDS; i++) write(LED[i], "0", 1); for(i = 0; i < LEDS; i++) close(LED[i]); for(i = 0; i < KBD_BUTTONS; i++) close(KBD[i]); ret = 0; } return ret; }



Nach oben