From 041ceda9e34e3b9d7b0f0adb24456390b0e51002 Mon Sep 17 00:00:00 2001 From: mb Date: Wed, 26 Oct 2011 14:57:17 +0000 Subject: [PATCH] Remove 'ucmb' packages git-svn-id: svn://svn.openwrt.org/openwrt/packages@28606 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- utils/ucmb-tools/Makefile | 41 -- utils/ucmb-tools/tools/Makefile | 17 - utils/ucmb-tools/tools/ucmb.c | 120 ---- utils/ucmb/Makefile | 65 -- utils/ucmb/driver/Makefile | 1 - utils/ucmb/driver/ucmb.c | 656 --------------------- utils/ucmb/driver/ucmb.h | 77 --- .../microcontroller_examples/atmel_avr8/ucmb.c | 233 -------- .../microcontroller_examples/atmel_avr8/ucmb.h | 24 - .../atmel_avr8_optimized/ucmb.c | 530 ----------------- .../atmel_avr8_optimized/ucmb.h | 36 -- 11 files changed, 1800 deletions(-) delete mode 100644 utils/ucmb-tools/Makefile delete mode 100644 utils/ucmb-tools/tools/Makefile delete mode 100644 utils/ucmb-tools/tools/ucmb.c delete mode 100644 utils/ucmb/Makefile delete mode 100644 utils/ucmb/driver/Makefile delete mode 100644 utils/ucmb/driver/ucmb.c delete mode 100644 utils/ucmb/driver/ucmb.h delete mode 100644 utils/ucmb/microcontroller_examples/atmel_avr8/ucmb.c delete mode 100644 utils/ucmb/microcontroller_examples/atmel_avr8/ucmb.h delete mode 100644 utils/ucmb/microcontroller_examples/atmel_avr8_optimized/ucmb.c delete mode 100644 utils/ucmb/microcontroller_examples/atmel_avr8_optimized/ucmb.h diff --git a/utils/ucmb-tools/Makefile b/utils/ucmb-tools/Makefile deleted file mode 100644 index 0204d8f4c..000000000 --- a/utils/ucmb-tools/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright (C) 2009 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. - -include $(TOPDIR)/rules.mk - -PKG_NAME:=ucmb-tools -PKG_RELEASE:=1 - -include $(INCLUDE_DIR)/package.mk - - -define Package/ucmb-tools - SECTION:=utils - CATEGORY:=Utilities - TITLE:=Microcontroller Message Bus tools - DEPENDS:=+kmod-ucmb - MAINTAINER:=Michael Buesch -endef - -define Package/ucmb-tools/description - Debugging tool for UCMB -endef - -define Build/Prepare - $(CP) ./tools/* $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - $(MAKE) -C $(PKG_BUILD_DIR) \ - $(TARGET_CONFIGURE_OPTS) CFLAGS="$(TARGET_CFLAGS) -I$(LINUX_DIR)/include" -endef - -define Package/ucmb-tools/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/ucmb $(1)/usr/bin/ -endef - -$(eval $(call BuildPackage,ucmb-tools)) diff --git a/utils/ucmb-tools/tools/Makefile b/utils/ucmb-tools/tools/Makefile deleted file mode 100644 index 406c3109e..000000000 --- a/utils/ucmb-tools/tools/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -INSTDIR = $(prefix)/usr/bin - -all: ucmb - -ucmb: ucmb.o - $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@ - $(STRIP) $@ - -%.o: %.c - $(CC) -c $(CFLAGS) $^ -o $@ - -install: ucmb - $(INSTALL) -d $(INSTDIR) - $(INSTALL) -m 0755 -o 0 -g 0 ucmb $(INSTDIR) - -clean: - rm -f ucmb *.o diff --git a/utils/ucmb-tools/tools/ucmb.c b/utils/ucmb-tools/tools/ucmb.c deleted file mode 100644 index 20cd1bfe8..000000000 --- a/utils/ucmb-tools/tools/ucmb.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Microcontroller Message Bus - * Userspace commandline utility - * - * Copyright (c) 2009 Michael Buesch - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - - -#define UCMB_DEV "/dev/ucmb" - -#define __UCMB_IOCTL ('U'|'C'|'M'|'B') -#define UCMB_IOCTL_RESETUC _IO(__UCMB_IOCTL, 0) -#define UCMB_IOCTL_GMSGDELAY _IOR(__UCMB_IOCTL, 1, unsigned int) -#define UCMB_IOCTL_SMSGDELAY _IOW(__UCMB_IOCTL, 2, unsigned int) - - -static void usage(int argc, char **argv) -{ - fprintf(stderr, "Usage: %s read|write|reset [" UCMB_DEV "]\n", argv[0]); -} - -int main(int argc, char **argv) -{ - const char *command, *devpath = UCMB_DEV; - int res, errcode = 0; - int ucmb_fd; - char *buf; - size_t count, buflen; - ssize_t nrbytes; - - if (argc != 2 && argc != 3) { - usage(argc, argv); - return 1; - } - if (argc == 3) - devpath = argv[2]; - command = argv[1]; - - ucmb_fd = open(devpath, O_RDWR); - if (ucmb_fd == -1) { - fprintf(stderr, "Failed to open %s\n", UCMB_DEV); - errcode = 1; - goto out; - } - - buflen = 4096; - buf = malloc(buflen); - if (!buf) { - fprintf(stderr, "Out of memory\n"); - errcode = 1; - goto out_close; - } - - if (strcasecmp(command, "read") == 0) { - nrbytes = read(ucmb_fd, buf, buflen); - if (nrbytes < 0) { - fprintf(stderr, "Failed to read UCMB: %s (%d)\n", - strerror(errno), errno); - errcode = 1; - goto out_free; - } - if (fwrite(buf, nrbytes, 1, stdout) != 1) { - fprintf(stderr, "Failed to write stdout\n"); - errcode = 1; - goto out_free; - } - } else if (strcasecmp(command, "write") == 0) { - count = fread(buf, 1, buflen, stdin); - if (!count) { - fprintf(stderr, "Failed to read stdin\n"); - errcode = 1; - goto out_free; - } - nrbytes = write(ucmb_fd, buf, count); - if (nrbytes != count) { - fprintf(stderr, "Failed to write UCMB: %s (%d)\n", - strerror(errno), errno); - errcode = 1; - goto out_free; - } - } else if (strcasecmp(command, "reset") == 0) { - res = ioctl(ucmb_fd, UCMB_IOCTL_RESETUC); - if (res) { - fprintf(stderr, "RESET ioctl failed: %s (%d)\n", - strerror(res < 0 ? -res : res), res); - errcode = 1; - goto out_free; - } - } else { - usage(argc, argv); - errcode = 1; - goto out_free; - } - -out_free: - free(buf); -out_close: - close(ucmb_fd); -out: - return errcode; -} diff --git a/utils/ucmb/Makefile b/utils/ucmb/Makefile deleted file mode 100644 index 09fc28ee3..000000000 --- a/utils/ucmb/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -# -# Copyright (C) 2010 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=ucmb -PKG_RELEASE:=2 - -include $(INCLUDE_DIR)/package.mk - - -define KernelPackage/ucmb - SUBMENU:=Other modules - DEPENDS:=@!LINUX_2_4 \ - @!LINUX_2_6_21 @!LINUX_2_6_22 @!LINUX_2_6_23 @!LINUX_2_6_24 \ - @!LINUX_2_6_25 @!LINUX_2_6_26 @!LINUX_2_6_27 \ - +kmod-spi-gpio +kmod-crc16 - KCONFIG:=CONFIG_SPI=y \ - CONFIG_SPI_MASTER=y - TITLE:=Microcontroller Message Bus - FILES:=$(PKG_BUILD_DIR)/ucmb.$(LINUX_KMOD_SUFFIX) - AUTOLOAD:=$(call AutoLoad,93,ucmb) - MAINTAINER:=Michael Buesch -endef - -define KernelPackage/ucmb/description - The Microcontroller Message Bus is a tiny SPI-GPIO based communication - channel used to talk to microcontrollers over GPIO pins. - The lowlevel protocol is CRC16 protected, so one can be pretty sure - that the data transmitted and received through the /dev/ucmb node is not corrupted. - So no further checks should be needed at upper protocol layers. - The device node considers every read/write to be one packet. The maximum packet - size is either PAGE_SIZE (at least 4kb) or the microcontroller specific packet size - limit, which is likely to be a lot smaller than PAGE_SIZE. - To register an ucmb device, simply create a struct ucmb_platform_data - and register it via ucmb_device_register() from another kernel module. - Example implementations for the microcontroller-side code can be found in - the utils/ucmb/microcontroller_examples subdirectory of the OpenWRT packages feed. -endef - -define Build/Prepare - $(CP) ./driver/* $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - $(MAKE) -C "$(LINUX_DIR)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - ARCH="$(LINUX_KARCH)" \ - SUBDIRS="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(BUILDFLAGS)" \ - modules -endef - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include - $(CP) \ - $(PKG_BUILD_DIR)/ucmb.h \ - $(1)/usr/include -endef - -$(eval $(call KernelPackage,ucmb)) diff --git a/utils/ucmb/driver/Makefile b/utils/ucmb/driver/Makefile deleted file mode 100644 index a232a4a09..000000000 --- a/utils/ucmb/driver/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-m := ucmb.o diff --git a/utils/ucmb/driver/ucmb.c b/utils/ucmb/driver/ucmb.c deleted file mode 100644 index bf4cd9b7c..000000000 --- a/utils/ucmb/driver/ucmb.c +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Microcontroller Message Bus - * Linux kernel driver - * - * Copyright (c) 2009-2010 Michael Buesch - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "ucmb.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - -#define PFX "ucmb: " - -#undef DEBUG - - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Microcontroller Message Bus"); -MODULE_AUTHOR("Michael Buesch"); - - -struct ucmb { - struct mutex mutex; - - bool is_open; - - unsigned int chunk_size; - unsigned int msg_delay_usec; - unsigned int gpio_reset; - bool reset_activelow; - - /* Misc character device driver */ - struct miscdevice mdev; - struct file_operations mdev_fops; - - /* SPI driver */ - struct spi_device *sdev; - - /* SPI-GPIO driver */ - struct spi_gpio_platform_data spi_gpio_pdata; - struct platform_device spi_gpio_pdev; -}; - -#define UCMB_MAX_MSG_DELAY (10 * 1000 * 1000) /* 10 seconds */ - - -struct ucmb_message_hdr { - __le16 magic; /* UCMB_MAGIC */ - __le16 len; /* Payload length (excluding header and footer) */ -} __attribute__((packed)); - -struct ucmb_message_footer { - __le16 crc; /* CRC of the header + payload. */ -} __attribute__((packed)); - -struct ucmb_status { - __le16 magic; /* UCMB_MAGIC */ - __le16 code; /* enum ucmb_status_code */ -} __attribute__((packed)); - -#define UCMB_MAGIC 0x1337 - -enum ucmb_status_code { - UCMB_STAT_OK = 0, - UCMB_STAT_EPROTO, /* Protocol format error */ - UCMB_STAT_ENOMEM, /* Out of memory */ - UCMB_STAT_E2BIG, /* Message too big */ - UCMB_STAT_ECRC, /* CRC error */ -}; - - -static int ucmb_spi_busnum_count = 1337; -static int ucmb_pdev_id_count; - - -static int __devinit ucmb_spi_probe(struct spi_device *sdev) -{ - return 0; -} - -static int __devexit ucmb_spi_remove(struct spi_device *sdev) -{ - return 0; -} - -static struct spi_driver ucmb_spi_driver = { - .driver = { - .name = "ucmb", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = ucmb_spi_probe, - .remove = __devexit_p(ucmb_spi_remove), -}; - -static void ucmb_toggle_reset_line(struct ucmb *ucmb, bool active) -{ - if (ucmb->reset_activelow) - active = !active; - gpio_set_value(ucmb->gpio_reset, active); -} - -static int ucmb_reset_microcontroller(struct ucmb *ucmb) -{ - if (ucmb->gpio_reset == UCMB_NO_RESET) - return -ENODEV; - - ucmb_toggle_reset_line(ucmb, 1); - msleep(50); - ucmb_toggle_reset_line(ucmb, 0); - msleep(50); - - return 0; -} - -static int ucmb_status_code_to_errno(enum ucmb_status_code code) -{ - switch (code) { - case UCMB_STAT_OK: - return 0; - case UCMB_STAT_EPROTO: - return -EPROTO; - case UCMB_STAT_ENOMEM: - return -ENOMEM; - case UCMB_STAT_E2BIG: - return -E2BIG; - case UCMB_STAT_ECRC: - return -EBADMSG; - } - return -EBUSY; -} - -static inline struct ucmb * filp_to_ucmb(struct file *filp) -{ - return container_of(filp->f_op, struct ucmb, mdev_fops); -} - -static int ucmb_open(struct inode *inode, struct file *filp) -{ - struct ucmb *ucmb = filp_to_ucmb(filp); - int err = 0; - - mutex_lock(&ucmb->mutex); - - if (ucmb->is_open) { - err = -EBUSY; - goto out_unlock; - } - ucmb->is_open = 1; - ucmb->msg_delay_usec = 0; - -out_unlock: - mutex_unlock(&ucmb->mutex); - - return err; -} - -static int ucmb_release(struct inode *inode, struct file *filp) -{ - struct ucmb *ucmb = filp_to_ucmb(filp); - - mutex_lock(&ucmb->mutex); - WARN_ON(!ucmb->is_open); - ucmb->is_open = 0; - mutex_unlock(&ucmb->mutex); - - return 0; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) -static long ucmb_ioctl(struct file *filp, - unsigned int cmd, unsigned long arg) -#else -static int ucmb_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -#endif -{ - struct ucmb *ucmb = filp_to_ucmb(filp); - int ret = 0; - - mutex_lock(&ucmb->mutex); - switch (cmd) { - case UCMB_IOCTL_RESETUC: - ret = ucmb_reset_microcontroller(ucmb); - break; - case UCMB_IOCTL_GMSGDELAY: - if (put_user(ucmb->msg_delay_usec, (unsigned int __user *)arg)) { - ret = -EFAULT; - break; - } - break; - case UCMB_IOCTL_SMSGDELAY: { - unsigned int msg_delay_usec; - - if (get_user(msg_delay_usec, (unsigned int __user *)arg)) { - ret = -EFAULT; - break; - } - if (msg_delay_usec > UCMB_MAX_MSG_DELAY) { - ret = -E2BIG; - break; - } - ucmb->msg_delay_usec = msg_delay_usec; - break; - } - default: - ret = -EINVAL; - } - mutex_unlock(&ucmb->mutex); - - return ret; -} - -static int ucmb_spi_write(struct ucmb *ucmb, const void *_buf, size_t size) -{ - const u8 *buf = _buf; - size_t i, chunk_size, current_size; - int err = 0; - - chunk_size = ucmb->chunk_size ? : size; - for (i = 0; i < size; i += chunk_size) { - current_size = chunk_size; - if (i + current_size > size) - current_size = size - i; - err = spi_write(ucmb->sdev, buf + i, current_size); - if (err) - goto out; - if (ucmb->chunk_size && need_resched()) - msleep(1); - } -out: - return err; -} - -static int ucmb_spi_read(struct ucmb *ucmb, void *_buf, size_t size) -{ - u8 *buf = _buf; - size_t i, chunk_size, current_size; - int err = 0; - - chunk_size = ucmb->chunk_size ? : size; - for (i = 0; i < size; i += chunk_size) { - current_size = chunk_size; - if (i + current_size > size) - current_size = size - i; - err = spi_read(ucmb->sdev, buf + i, current_size); - if (err) - goto out; - if (ucmb->chunk_size && need_resched()) - msleep(1); - } -out: - return err; -} - -static ssize_t ucmb_read(struct file *filp, char __user *user_buf, - size_t size, loff_t *offp) -{ - struct ucmb *ucmb = filp_to_ucmb(filp); - u8 *buf; - int res, err; - struct ucmb_message_hdr hdr; - struct ucmb_message_footer footer; - struct ucmb_status status = { .magic = cpu_to_le16(UCMB_MAGIC), }; - u16 crc = 0xFFFF; - - mutex_lock(&ucmb->mutex); - - size = min_t(size_t, size, PAGE_SIZE); - - err = -ENOMEM; - buf = (char *)__get_free_page(GFP_KERNEL); - if (!buf) - goto out; - - err = ucmb_spi_read(ucmb, &hdr, sizeof(hdr)); - if (err) - goto out_free; -#ifdef DEBUG - printk(KERN_DEBUG PFX "Received message header 0x%04X 0x%04X\n", - le16_to_cpu(hdr.magic), le16_to_cpu(hdr.len)); -#endif - err = -EPROTO; - if (hdr.magic != cpu_to_le16(UCMB_MAGIC)) - goto out_free; - err = -ENOBUFS; - if (size < le16_to_cpu(hdr.len)) - goto out_free; - size = le16_to_cpu(hdr.len); - err = ucmb_spi_read(ucmb, buf, size); - if (err) - goto out_free; - err = ucmb_spi_read(ucmb, &footer, sizeof(footer)); - if (err) - goto out_free; - - crc = crc16(crc, (u8 *)&hdr, sizeof(hdr)); - crc = crc16(crc, buf, size); - crc ^= 0xFFFF; - if (crc != le16_to_cpu(footer.crc)) { - err = -EPROTO; - status.code = UCMB_STAT_ECRC; - goto out_send_status; - } - - if (copy_to_user(user_buf, buf, size)) { - err = -EFAULT; - status.code = UCMB_STAT_ENOMEM; - goto out_send_status; - } - - status.code = UCMB_STAT_OK; - err = 0; - -out_send_status: - res = ucmb_spi_write(ucmb, &status, sizeof(status)); - if (res && !err) - err = res; -out_free: - free_page((unsigned long)buf); -out: - mutex_unlock(&ucmb->mutex); - - return err ? err : size; -} - -static ssize_t ucmb_write(struct file *filp, const char __user *user_buf, - size_t size, loff_t *offp) -{ - struct ucmb *ucmb = filp_to_ucmb(filp); - u8 *buf; - int err; - struct ucmb_message_hdr hdr = { .magic = cpu_to_le16(UCMB_MAGIC), }; - struct ucmb_message_footer footer = { .crc = 0xFFFF, }; - struct ucmb_status status; - - mutex_lock(&ucmb->mutex); - - err = -ENOMEM; - buf = (char *)__get_free_page(GFP_KERNEL); - if (!buf) - goto out; - - size = min_t(size_t, PAGE_SIZE, size); - err = -EFAULT; - if (copy_from_user(buf, user_buf, size)) - goto out_free; - hdr.len = cpu_to_le16(size); - - footer.crc = crc16(footer.crc, (u8 *)&hdr, sizeof(hdr)); - footer.crc = crc16(footer.crc, buf, size); - footer.crc ^= 0xFFFF; - - err = ucmb_spi_write(ucmb, &hdr, sizeof(hdr)); - if (err) - goto out_free; - err = ucmb_spi_write(ucmb, buf, size); - if (err) - goto out_free; - err = ucmb_spi_write(ucmb, &footer, sizeof(footer)); - if (err) - goto out_free; - - if (ucmb->msg_delay_usec) { - /* The microcontroller deserves some time to process the message. */ - if (ucmb->msg_delay_usec >= 1000000) { - ssleep(ucmb->msg_delay_usec / 1000000); - msleep(DIV_ROUND_UP(ucmb->msg_delay_usec % 1000000, 1000)); - } else if (ucmb->msg_delay_usec >= 1000) { - msleep(DIV_ROUND_UP(ucmb->msg_delay_usec, 1000)); - } else - udelay(ucmb->msg_delay_usec); - } - - /* Get the status code. */ - err = ucmb_spi_read(ucmb, &status, sizeof(status)); - if (err) - goto out_free; -#ifdef DEBUG - printk(KERN_DEBUG PFX "Sent message. Status report: 0x%04X 0x%04X\n", - le16_to_cpu(status.magic), le16_to_cpu(status.code)); -#endif - err = -EPROTO; - if (status.magic != cpu_to_le16(UCMB_MAGIC)) - goto out_free; - err = ucmb_status_code_to_errno(le16_to_cpu(status.code)); - if (err) - goto out_free; - -out_free: - free_page((unsigned long)buf); -out: - mutex_unlock(&ucmb->mutex); - - return err ? err : size; -} - -static int __devinit ucmb_probe(struct platform_device *pdev) -{ - struct ucmb_platform_data *pdata; - struct ucmb *ucmb; - int err; - const int bus_num = ucmb_spi_busnum_count++; - struct spi_bitbang *bb; - - pdata = pdev->dev.platform_data; - if (!pdata) - return -ENXIO; - - ucmb = kzalloc(sizeof(struct ucmb), GFP_KERNEL); - if (!ucmb) - return -ENOMEM; - mutex_init(&ucmb->mutex); - ucmb->gpio_reset = pdata->gpio_reset; - ucmb->reset_activelow = pdata->reset_activelow; - ucmb->chunk_size = pdata->chunk_size; - -#ifdef CONFIG_PREEMPT - /* A preemptible kernel does not need to sleep between - * chunks, because it can sleep at desire (if IRQs are enabled). - * So transmit/receive it all in one go. */ - ucmb->chunk_size = 0; -#endif - - /* Create the SPI GPIO bus master. */ - -#ifdef CONFIG_SPI_GPIO_MODULE - err = request_module("spi_gpio"); - if (err) - printk(KERN_WARNING PFX "Failed to request spi_gpio module\n"); -#endif /* CONFIG_SPI_GPIO_MODULE */ - - ucmb->spi_gpio_pdata.sck = pdata->gpio_sck; - ucmb->spi_gpio_pdata.mosi = pdata->gpio_mosi; - ucmb->spi_gpio_pdata.miso = pdata->gpio_miso; - ucmb->spi_gpio_pdata.num_chipselect = 1; - - ucmb->spi_gpio_pdev.name = "spi_gpio"; - ucmb->spi_gpio_pdev.id = bus_num; - ucmb->spi_gpio_pdev.dev.platform_data = &ucmb->spi_gpio_pdata; - - err = platform_device_register(&ucmb->spi_gpio_pdev); - if (err) { - printk(KERN_ERR PFX "Failed to register SPI-GPIO platform device\n"); - goto err_free_ucmb; - } - bb = platform_get_drvdata(&ucmb->spi_gpio_pdev); - if (!bb || !bb->master) { - printk(KERN_ERR PFX "No bitbanged master device found.\n"); - goto err_unreg_spi_gpio_pdev; - } - - /* Create the SPI device. */ - - ucmb->sdev = spi_alloc_device(bb->master); - if (!ucmb->sdev) { - printk(KERN_ERR PFX "Failed to allocate SPI device\n"); - goto err_unreg_spi_gpio_pdev; - } - ucmb->sdev->max_speed_hz = pdata->max_speed_hz; - ucmb->sdev->chip_select = 0; - ucmb->sdev->mode = pdata->mode; - strlcpy(ucmb->sdev->modalias, "ucmb", /* We are the SPI driver. */ - sizeof(ucmb->sdev->modalias)); - ucmb->sdev->controller_data = (void *)pdata->gpio_cs; - err = spi_add_device(ucmb->sdev); - if (err) { - printk(KERN_ERR PFX "Failed to add SPI device\n"); - goto err_free_spi_device; - } - - /* Initialize the RESET line. */ - - if (pdata->gpio_reset != UCMB_NO_RESET) { - err = gpio_request(pdata->gpio_reset, pdata->name); - if (err) { - printk(KERN_ERR PFX - "Failed to request RESET GPIO line\n"); - goto err_unreg_spi_device; - } - err = gpio_direction_output(pdata->gpio_reset, - pdata->reset_activelow); - if (err) { - printk(KERN_ERR PFX - "Failed to set RESET GPIO direction\n"); - goto err_free_reset_gpio; - } - ucmb_reset_microcontroller(ucmb); - } - - /* Create the Misc char device. */ - - ucmb->mdev.minor = MISC_DYNAMIC_MINOR; - ucmb->mdev.name = pdata->name; - ucmb->mdev.parent = &pdev->dev; - ucmb->mdev_fops.open = ucmb_open; - ucmb->mdev_fops.release = ucmb_release; - ucmb->mdev_fops.read = ucmb_read; - ucmb->mdev_fops.write = ucmb_write; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) - ucmb->mdev_fops.unlocked_ioctl = ucmb_ioctl; -#else - ucmb->mdev_fops.ioctl = ucmb_ioctl; -#endif - ucmb->mdev.fops = &ucmb->mdev_fops; - - err = misc_register(&ucmb->mdev); - if (err) { - printk(KERN_ERR PFX "Failed to register miscdev %s\n", - ucmb->mdev.name); - goto err_free_reset_gpio; - } - - platform_set_drvdata(pdev, ucmb); - - printk(KERN_INFO PFX "Registered message bus \"%s\"\n", pdata->name); - - return 0; - -err_free_reset_gpio: - if (pdata->gpio_reset != UCMB_NO_RESET) - gpio_free(pdata->gpio_reset); -err_unreg_spi_device: - spi_unregister_device(ucmb->sdev); -err_free_spi_device: - spi_dev_put(ucmb->sdev); -err_unreg_spi_gpio_pdev: - platform_device_unregister(&ucmb->spi_gpio_pdev); -err_free_ucmb: - kfree(ucmb); - - return err; -} - -static int __devexit ucmb_remove(struct platform_device *pdev) -{ - struct ucmb *ucmb = platform_get_drvdata(pdev); - int err; - - err = misc_deregister(&ucmb->mdev); - if (err) { - printk(KERN_ERR PFX "Failed to unregister miscdev %s\n", - ucmb->mdev.name); - } - if (ucmb->gpio_reset != UCMB_NO_RESET) - gpio_free(ucmb->gpio_reset); - spi_unregister_device(ucmb->sdev); - spi_dev_put(ucmb->sdev); - platform_device_unregister(&ucmb->spi_gpio_pdev); - - kfree(ucmb); - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver ucmb_driver = { - .driver = { - .name = "ucmb", - .owner = THIS_MODULE, - }, - .probe = ucmb_probe, - .remove = __devexit_p(ucmb_remove), -}; - -int ucmb_device_register(struct ucmb_platform_data *pdata) -{ - struct platform_device *pdev; - int err; - - pdev = platform_device_alloc("ucmb", ucmb_pdev_id_count++); - if (!pdev) { - printk(KERN_ERR PFX "Failed to allocate platform device.\n"); - return -ENOMEM; - } - err = platform_device_add_data(pdev, pdata, sizeof(*pdata)); - if (err) { - printk(KERN_ERR PFX "Failed to add platform data.\n"); - platform_device_put(pdev); - return err; - } - err = platform_device_add(pdev); - if (err) { - printk(KERN_ERR PFX "Failed to register platform device.\n"); - platform_device_put(pdev); - return err; - } - pdata->pdev = pdev; - - return 0; -} -EXPORT_SYMBOL(ucmb_device_register); - -void ucmb_device_unregister(struct ucmb_platform_data *pdata) -{ - if (!pdata->pdev) - return; - platform_device_unregister(pdata->pdev); - platform_device_put(pdata->pdev); - pdata->pdev = NULL; -} -EXPORT_SYMBOL(ucmb_device_unregister); - -static int ucmb_modinit(void) -{ - int err; - - printk(KERN_INFO "Microcontroller message bus driver\n"); - - err = spi_register_driver(&ucmb_spi_driver); - if (err) { - printk(KERN_ERR PFX "Failed to register SPI driver\n"); - return err; - } - err = platform_driver_register(&ucmb_driver); - if (err) { - printk(KERN_ERR PFX "Failed to register platform driver\n"); - spi_unregister_driver(&ucmb_spi_driver); - return err; - } - - return 0; -} -subsys_initcall(ucmb_modinit); - -static void ucmb_modexit(void) -{ - platform_driver_unregister(&ucmb_driver); - spi_unregister_driver(&ucmb_spi_driver); -} -module_exit(ucmb_modexit); diff --git a/utils/ucmb/driver/ucmb.h b/utils/ucmb/driver/ucmb.h deleted file mode 100644 index c0d35d207..000000000 --- a/utils/ucmb/driver/ucmb.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef LINUX_UCMB_H_ -#define LINUX_UCMB_H_ - -#include -#include - - -/* IOCTLs */ -#define __UCMB_IOCTL ('U'|'C'|'M'|'B') - -/** UCMB_IOCTL_RESETUC - Reset the microcontroller. */ -#define UCMB_IOCTL_RESETUC _IO(__UCMB_IOCTL, 0) -/** UCMB_IOCTL_GMSGDELAY - Get the delay to wait before fetching the status. */ -#define UCMB_IOCTL_GMSGDELAY _IOR(__UCMB_IOCTL, 1, unsigned int) -/** UCMB_IOCTL_SMSGDELAY - Set the delay to wait before fetching the status. */ -#define UCMB_IOCTL_SMSGDELAY _IOW(__UCMB_IOCTL, 2, unsigned int) - - -#ifdef __KERNEL__ - -#include -#include -#include - -/** - * struct ucmb_platform_data - UCMB device descriptor - * - * @name: The name of the device. This will also be the name of - * the misc char device. - * - * @gpio_cs: The chipselect GPIO pin. Can be SPI_GPIO_NO_CHIPSELECT, - * if chipselect is not used. - * @gpio_sck: The clock GPIO pin. - * @gpio_miso: The master-in slave-out GPIO pin. - * @gpio_mosi: The master-out slave-in GPIO pin. - * - * @gpio_reset: The GPIO pin to the microcontroller reset line. - * Can be UCMB_NO_RESET, if reset GPIO is not used. - * @reset_activelow: If true, @gpio_reset is considered to be active - * on logical 0 (inverted). - * - * @mode: The SPI bus mode. SPI_MODE_* - * @max_speed_hz: The bus speed, in Hz. If zero the speed is not limited. - * @chunk_size: The maximum chunk size to transmit/receive in one go - * without sleeping. The kernel will be allowed to sleep - * after each chunk. - * If set to 0, the whole data will be transmitted/received - * in one big rush without sleeping. Note that this might hurt - * system responsiveness, if the kernel is not preemptible. - * If CONFIG_PREEMPT is enabled, chunk_size will be forced to 0. - */ -struct ucmb_platform_data { - const char *name; - - unsigned long gpio_cs; - unsigned int gpio_sck; - unsigned int gpio_miso; - unsigned int gpio_mosi; - - unsigned int gpio_reset; - bool reset_activelow; - - u8 mode; - u32 max_speed_hz; - unsigned int chunk_size; - - struct platform_device *pdev; /* internal */ -}; - -#define UCMB_NO_RESET ((unsigned int)-1) - -int ucmb_device_register(struct ucmb_platform_data *pdata); -void ucmb_device_unregister(struct ucmb_platform_data *pdata); - - -#endif /* __KERNEL__ */ -#endif /* LINUX_UCMB_H_ */ diff --git a/utils/ucmb/microcontroller_examples/atmel_avr8/ucmb.c b/utils/ucmb/microcontroller_examples/atmel_avr8/ucmb.c deleted file mode 100644 index fb2bc944b..000000000 --- a/utils/ucmb/microcontroller_examples/atmel_avr8/ucmb.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Microcontroller message bus - * uc-side slave implementation for Atmel AVR8 - * - * The gcc compiler always treats multi-byte variables as litte-endian. - * So no explicit endianness conversions are done on the message header, - * footer and status data structures. - * - * Copyright (C) 2009 Michael Buesch - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "ucmb.h" - -#include -#include -#include -#include - - -struct ucmb_message_hdr { - uint16_t magic; /* UCMB_MAGIC */ - uint16_t len; /* Payload length (excluding header and footer) */ -} __attribute__((packed)); - -struct ucmb_message_footer { - uint16_t crc; /* CRC of the header + payload. */ -} __attribute__((packed)); - -struct ucmb_status { - uint16_t magic; /* UCMB_MAGIC */ - uint16_t code; /* enum ucmb_status_code */ -} __attribute__((packed)); - -#define UCMB_MAGIC 0x1337 - -enum ucmb_status_code { - UCMB_STAT_OK = 0, - UCMB_STAT_EPROTO, /* Protocol format error */ - UCMB_STAT_ENOMEM, /* Out of memory */ - UCMB_STAT_E2BIG, /* Message too big */ - UCMB_STAT_ECRC, /* CRC error */ -}; - - -static uint8_t ucmb_buf[sizeof(struct ucmb_message_hdr) + - UCMB_MAX_MSG_LEN + - sizeof(struct ucmb_message_footer)]; -static uint16_t ucmb_buf_ptr; -static struct ucmb_status status_buf; -static uint16_t ucmb_send_message_len; - -/* Statemachine */ -static uint8_t ucmb_state; -enum { - UCMB_ST_LISTEN, /* Listen for incoming messages. */ - UCMB_ST_SENDSTATUS, /* Send the status report. */ - UCMB_ST_SENDMESSAGE, /* Send the message. */ - UCMB_ST_RETRSTATUS, /* Retrieve the status report. */ -}; - -#define TRAILING 1 - - -static void ucmb_send_next_byte(void) -{ - switch (ucmb_state) { - case UCMB_ST_SENDSTATUS: { - const uint8_t *st = (const uint8_t *)&status_buf; - - if (ucmb_buf_ptr < sizeof(struct ucmb_status)) - SPDR = st[ucmb_buf_ptr]; - ucmb_buf_ptr++; - if (ucmb_buf_ptr == sizeof(struct ucmb_status) + TRAILING) { - ucmb_buf_ptr = 0; - if (ucmb_send_message_len) { - ucmb_state = UCMB_ST_SENDMESSAGE; - goto st_sendmessage; - } else - ucmb_state = UCMB_ST_LISTEN; - } - break; - } - case UCMB_ST_SENDMESSAGE: { - st_sendmessage:; - uint16_t full_length = sizeof(struct ucmb_message_hdr) + - ucmb_send_message_len + - sizeof(struct ucmb_message_footer); - if (ucmb_buf_ptr < full_length) - SPDR = ucmb_buf[ucmb_buf_ptr]; - ucmb_buf_ptr++; - if (ucmb_buf_ptr == full_length + TRAILING) { - ucmb_send_message_len = 0; - ucmb_buf_ptr = 0; - ucmb_state = UCMB_ST_RETRSTATUS; - } - break; - } } -} - -static uint16_t crc16_block_update(uint16_t crc, const void *_data, uint16_t size) -{ - const uint8_t *data = _data; - - while (size) { - crc = _crc16_update(crc, *data); - data++; - size--; - } - - return crc; -} - -static uint16_t ucmb_calc_msg_buffer_crc(void) -{ - const struct ucmb_message_hdr *hdr; - uint16_t crc = 0xFFFF; - - hdr = (const struct ucmb_message_hdr *)ucmb_buf; - crc = crc16_block_update(crc, ucmb_buf, - sizeof(struct ucmb_message_hdr) + hdr->len); - crc ^= 0xFFFF; - - return crc; -} - -/* SPI data transfer interrupt. */ -ISR(SPI_STC_vect) -{ - uint8_t data; - - data = SPDR; - SPDR = 0; - - switch (ucmb_state) { - case UCMB_ST_LISTEN: { - struct ucmb_message_hdr *hdr; - struct ucmb_message_footer *footer; - - if (ucmb_buf_ptr < sizeof(ucmb_buf)) - ucmb_buf[ucmb_buf_ptr] = data; - ucmb_buf_ptr++; - if (ucmb_buf_ptr < sizeof(struct ucmb_message_hdr)) - return; /* Header RX not complete. */ - hdr = (struct ucmb_message_hdr *)ucmb_buf; - if (ucmb_buf_ptr == sizeof(struct ucmb_message_hdr)) { - if (hdr->magic != UCMB_MAGIC) { - /* Invalid magic! Reset. */ - ucmb_buf_ptr = 0; - return; - } - if (hdr->len > 0x8000) { - /* Completely bogus length! Reset. */ - ucmb_buf_ptr = 0; - return; - } - return; - } - - if (ucmb_buf_ptr == sizeof(struct ucmb_message_hdr) + - sizeof(struct ucmb_message_footer) + - hdr->len) { - status_buf.magic = UCMB_MAGIC; - status_buf.code = UCMB_STAT_OK; - if (ucmb_buf_ptr > sizeof(ucmb_buf)) { - /* Message is way too big and was truncated. */ - status_buf.code = UCMB_STAT_E2BIG; - } else { - footer = (struct ucmb_message_footer *)( - ucmb_buf + sizeof(struct ucmb_message_hdr) + - hdr->len); - if (ucmb_calc_msg_buffer_crc() != footer->crc) - status_buf.code = UCMB_STAT_ECRC; - } - ucmb_state = UCMB_ST_SENDSTATUS; - ucmb_buf_ptr = 0; - ucmb_send_next_byte(); - - if (status_buf.code != UCMB_STAT_OK) - return; /* Corrupt message. Don't pass it to user code. */ - - ucmb_send_message_len = ucmb_rx_message( - ucmb_buf + sizeof(struct ucmb_message_hdr), - hdr->len); - if (ucmb_send_message_len) { - footer = (struct ucmb_message_footer *)( - ucmb_buf + sizeof(struct ucmb_message_hdr) + - ucmb_send_message_len); - - hdr->magic = UCMB_MAGIC; - hdr->len = ucmb_send_message_len; - footer->crc = ucmb_calc_msg_buffer_crc(); - } - } - break; - } - case UCMB_ST_SENDSTATUS: - case UCMB_ST_SENDMESSAGE: - ucmb_send_next_byte(); - break; - case UCMB_ST_RETRSTATUS: { - uint8_t *st = (uint8_t *)&status_buf; - - st[ucmb_buf_ptr++] = data; - if (ucmb_buf_ptr == sizeof(struct ucmb_status)) { - /* We could possibly handle the status report here... */ - ucmb_buf_ptr = 0; - ucmb_state = UCMB_ST_LISTEN; - } - break; - } } -} - -void ucmb_init(void) -{ - ucmb_state = UCMB_ST_LISTEN; - - /* SPI slave mode 0 with IRQ enabled. */ - DDRB |= (1 << 4/*MISO*/); - DDRB &= ~((1 << 5/*SCK*/) | (1 << 3/*MOSI*/) | (1 << 2/*SS*/)); - SPCR = (1 << SPE) | (1 << SPIE) /*| (1 << CPOL) | (1 << CPHA)*/; - (void)SPSR; /* clear state */ - (void)SPDR; /* clear state */ -} diff --git a/utils/ucmb/microcontroller_examples/atmel_avr8/ucmb.h b/utils/ucmb/microcontroller_examples/atmel_avr8/ucmb.h deleted file mode 100644 index 9ecb92f43..000000000 --- a/utils/ucmb/microcontroller_examples/atmel_avr8/ucmb.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef UCMB_AVR8_H_ -#define UCMB_AVR8_H_ - -#include - - -/* Max length of the message payload. */ -#define UCMB_MAX_MSG_LEN 0x200 - -/* ucmb_rx_message - Message receive callback. - * Define this elsewhere. It's called on successful retrieval - * of a new message. - * If a reply message has to be transferred after this one, put the - * message payload into the "payload" buffer and return the number - * of bytes to transmit. If no reply message is needed, return 0. - * Note that the "payload" buffer always has a size of UCMB_MAX_MSG_LEN. - */ -extern uint16_t ucmb_rx_message(uint8_t *payload, - uint16_t payload_length); - -/* Initialize the UCMB subsystem. */ -void ucmb_init(void); - -#endif /* UCMB_AVR8_H_ */ diff --git a/utils/ucmb/microcontroller_examples/atmel_avr8_optimized/ucmb.c b/utils/ucmb/microcontroller_examples/atmel_avr8_optimized/ucmb.c deleted file mode 100644 index b605baa8d..000000000 --- a/utils/ucmb/microcontroller_examples/atmel_avr8_optimized/ucmb.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Microcontroller message bus - * uc-side slave implementation for Atmel AVR8 - * - * The gcc compiler always treats multi-byte variables as litte-endian. - * So no explicit endianness conversions are done on the message header, - * footer and status data structures. - * - * This hotpath-assembly implementation is about twice as fast - * as the C implementation. - * - * Copyright (C) 2009 Michael Buesch - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "ucmb.h" - -#include -#include -#include -#include -#include - - -#ifndef __GNUC__ -# error "Need the GNU C compiler" -#endif - -#undef __naked -#define __naked __attribute__((__naked__)) -#undef __used -#define __used __attribute__((__used__)) -#undef __noret -#define __noret __attribute__((__noreturn__)) -#undef offsetof -#define offsetof(type, member) ((size_t)&((type *)0)->member) -#undef unlikely -#define unlikely(x) __builtin_expect(!!(x), 0) -#undef mb -#define mb() __asm__ __volatile__("" : : : "memory") /* memory barrier */ -#ifndef ucmb_errorlog -# define ucmb_errorlog(message) do { /* nothing */ } while (0) -#endif - - -struct ucmb_message_hdr { - uint16_t magic; /* UCMB_MAGIC */ - uint16_t len; /* Payload length (excluding header and footer) */ -} __attribute__((packed)); - -struct ucmb_message_footer { - uint16_t crc; /* CRC of the header + payload. */ -} __attribute__((packed)); - -struct ucmb_status { - uint16_t magic; /* UCMB_MAGIC */ - uint16_t code; /* enum ucmb_status_code */ -} __attribute__((packed)); - -#define UCMB_MAGIC 0x1337 - -enum ucmb_status_code { - UCMB_STAT_OK = 0, - UCMB_STAT_EPROTO, /* Protocol format error */ - UCMB_STAT_ENOMEM, /* Out of memory */ - UCMB_STAT_E2BIG, /* Message too big */ - UCMB_STAT_ECRC, /* CRC error */ -}; - - -static uint8_t ucmb_buf[sizeof(struct ucmb_message_hdr) + - UCMB_MAX_MSG_LEN + - sizeof(struct ucmb_message_footer)] __used; -static uint16_t ucmb_buf_ptr __used; -static struct ucmb_status status_buf __used; -static uint16_t ucmb_send_message_len __used; -static uint8_t ucmb_received_message; - -/* The current IRQ handler */ -static void (*ucmb_interrupt_handler)(void) __used; - - -/* Polynomial: x^16 + x^15 + x^2 + 1 */ -static const prog_uint16_t crc16_table[256] = { - 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, - 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, - 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, - 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, - 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, - 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, - 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, - 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, - 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, - 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, - 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, - 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, - 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, - 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, - 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, - 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, - 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, - 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, - 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, - 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, - 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, - 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, - 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, - 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, - 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, - 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, - 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, - 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, - 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, - 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, - 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, - 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 -}; - -static inline uint16_t crc16_block_update(uint16_t crc, const void *_data, uint16_t size) -{ - const uint8_t *data = _data; - uint8_t offset; - - while (size--) { - wdt_reset(); - offset = crc ^ *data; - crc = (crc >> 8) ^ pgm_read_word(&crc16_table[offset]); - data++; - } - - return crc; -} - -static inline uint16_t ucmb_calc_msg_buffer_crc(void) -{ - const struct ucmb_message_hdr *hdr; - uint16_t crc = 0xFFFF; - - hdr = (const struct ucmb_message_hdr *)ucmb_buf; - crc = crc16_block_update(crc, ucmb_buf, - sizeof(struct ucmb_message_hdr) + hdr->len); - crc ^= 0xFFFF; - - return crc; -} - -/* The generic interrupt handler. - * This just branches to the state specific handler. - */ -ISR(SPI_STC_vect) __naked; -ISR(SPI_STC_vect) -{ - __asm__ __volatile__( -" ; UCMB generic interrupt handler \n" -" push __tmp_reg__ \n" -" in __tmp_reg__, __SREG__ \n" -" push r30 \n" -" push r31 \n" -" lds r30, ucmb_interrupt_handler + 0 \n" -" lds r31, ucmb_interrupt_handler + 1 \n" -" ijmp ; Jump to the real handler \n" - ); -} -#define UCMB_IRQ_EPILOGUE \ -" ; UCMB interrupt epilogue (start) \n"\ -" pop r31 \n"\ -" pop r30 \n"\ -" out __SREG__, __tmp_reg__ \n"\ -" pop __tmp_reg__ \n"\ -" reti \n"\ -" ; UCMB interrupt epilogue (end) \n" - -static void __naked __used ucmb_handler_LISTEN(void) -{ - __asm__ __volatile__( -" push r16 \n" -" push r17 \n" -" push r18 \n" -" lds r16, ucmb_buf_ptr + 0 \n" -" lds r17, ucmb_buf_ptr + 1 \n" -" ldi r18, hi8(%[sizeof_buf]) \n" -" cpi r16, lo8(%[sizeof_buf]) \n" -" cpc r17, r18 \n" -" in r18, %[_SPDR] \n" -" brsh 1f ; overflow \n" -" ; Store SPDR in the buffer \n" -" movw r30, r16 \n" -" subi r30, lo8(-(ucmb_buf)) \n" -" sbci r31, hi8(-(ucmb_buf)) \n" -" st Z, r18 \n" -"1: \n" -" ; Increment the buffer pointer \n" -" subi r16, lo8(-1) \n" -" sbci r17, hi8(-1) \n" -" sts ucmb_buf_ptr + 0, r16 \n" -" sts ucmb_buf_ptr + 1, r17 \n" -" cpi r17, 0 \n" -" brne 1f \n" -" cpi r16, %[sizeof_msg_hdr] \n" -" breq hdr_sanity_check ; buf_ptr == hdrlen \n" -" brlo st_listen_out ; buf_ptr < hdrlen \n" -"1: \n" -" ; Get payload length from header \n" -" lds r30, (ucmb_buf + %[offsetof_hdr_len] + 0) \n" -" lds r31, (ucmb_buf + %[offsetof_hdr_len] + 1) \n" -" ; Add header and footer length to get full length \n" -" subi r30, lo8(-(%[sizeof_msg_hdr] + %[sizeof_msg_footer])) \n" -" sbci r31, hi8(-(%[sizeof_msg_hdr] + %[sizeof_msg_footer])) \n" -" ; Check if we have the full packet \n" -" cp r30, r16 \n" -" cpc r31, r17 \n" -" breq st_listen_have_full_packet \n" -"st_listen_out: \n" -" pop r18 \n" -" pop r17 \n" -" pop r16 \n" -UCMB_IRQ_EPILOGUE /* reti */ -" \n" -"hdr_sanity_check: \n" -" lds r30, (ucmb_buf + %[offsetof_hdr_magic] + 0) \n" -" lds r31, (ucmb_buf + %[offsetof_hdr_magic] + 1) \n" -" ldi r18, hi8(%[_UCMB_MAGIC]) \n" -" cpi r30, lo8(%[_UCMB_MAGIC]) \n" -" cpc r31, r18 \n" -" brne invalid_hdr_magic \n" -" lds r30, (ucmb_buf + %[offsetof_hdr_len] + 0) \n" -" lds r31, (ucmb_buf + %[offsetof_hdr_len] + 1) \n" -" ldi r18, hi8(0x8001) \n" -" cpi r30, lo8(0x8001) \n" -" cpc r31, r18 \n" -" brsh bogus_payload_len \n" -" rjmp st_listen_out \n" -" \n" -"invalid_hdr_magic: \n" -" ; Invalid magic number in the packet header. Reset. \n" -"bogus_payload_len: \n" -" ; Bogus payload length in packet header. Reset. \n" -" clr r18 \n" -" sts ucmb_buf_ptr + 0, r18 \n" -" sts ucmb_buf_ptr + 1, r18 \n" -" rjmp st_listen_out \n" -" \n" -"st_listen_have_full_packet: \n" -" ; We have the full packet. Any SPI transfer is stopped \n" -" ; while we are processing the packet, so this \n" -" ; is a slowpath. \n" -" ; Disable SPI and pass control to ucmb_work to \n" -" ; handle the message. \n" -" cbi %[_SPCR], %[_SPIE] \n" -" ldi r18, 1 \n" -" sts ucmb_received_message, r18 \n" -" rjmp st_listen_out \n" - : /* none */ - : [sizeof_buf] "i" (sizeof(ucmb_buf)) - , [sizeof_msg_hdr] "M" (sizeof(struct ucmb_message_hdr)) - , [sizeof_msg_footer] "M" (sizeof(struct ucmb_message_footer)) - , [offsetof_hdr_magic] "M" (offsetof(struct ucmb_message_hdr, magic)) - , [offsetof_hdr_len] "M" (offsetof(struct ucmb_message_hdr, len)) - , [_SPDR] "M" (_SFR_IO_ADDR(SPDR)) - , [_SPCR] "M" (_SFR_IO_ADDR(SPCR)) - , [_SPIE] "i" (SPIE) - , [_UCMB_MAGIC] "i" (UCMB_MAGIC) - : "memory" - ); -} - -static void __naked __used ucmb_handler_SENDSTATUS(void) -{ - __asm__ __volatile__( -" push r16 \n" -/*" push r17 \n" */ -" push r18 \n" -" lds r16, ucmb_buf_ptr + 0 \n" -" cpi r16, %[sizeof_ucmb_status] \n" -" brsh 1f ; This is the trailing byte \n" -" ; Write the next byte from status_buf to SPDR \n" -" mov r30, r16 \n" -" clr r31 \n" -" subi r30, lo8(-(status_buf)) \n" -" sbci r31, hi8(-(status_buf)) \n" -" ld r18, Z \n" -" out %[_SPDR], r18 \n" -"1: \n" -" subi r16, lo8(-1) \n" -" sts ucmb_buf_ptr + 0, r16 \n" -" cpi r16, (%[sizeof_ucmb_status] + 1) \n" -" brne st_sendstatus_out \n" -" ; Finished. Sent all status_buf bytes + trailing byte. \n" -" clr r18 \n" -" sts ucmb_buf_ptr + 0, r18 \n" -" ; Switch back to listening state... \n" -" ldi r18, lo8(gs(ucmb_handler_LISTEN)) \n" -" sts ucmb_interrupt_handler + 0, r18 \n" -" ldi r18, hi8(gs(ucmb_handler_LISTEN)) \n" -" sts ucmb_interrupt_handler + 1, r18 \n" -" ; ...if we have no pending transmission \n" -" lds r30, ucmb_send_message_len + 0 \n" -" lds r31, ucmb_send_message_len + 1 \n" -" clr r18 \n" -" cpi r30, 0 \n" -" cpc r31, r18 \n" -" breq st_sendstatus_out \n" -" ; Switch status to SENDMESSAGE and send the first byte. \n" -" ldi r18, lo8(gs(ucmb_handler_SENDMESSAGE)) \n" -" sts ucmb_interrupt_handler + 0, r18 \n" -" ldi r18, hi8(gs(ucmb_handler_SENDMESSAGE)) \n" -" sts ucmb_interrupt_handler + 1, r18 \n" -" ; Send the first byte \n" -" lds r18, ucmb_buf + 0 \n" -" out %[_SPDR], r18 \n" -" ldi r18, 1 \n" -" sts ucmb_buf_ptr + 0, r18 \n" -"st_sendstatus_out: \n" -" pop r18 \n" -/*" pop r17 \n"*/ -" pop r16 \n" -UCMB_IRQ_EPILOGUE /* reti */ - : /* none */ - : [sizeof_ucmb_status] "M" (sizeof(struct ucmb_status)) - , [_SPDR] "M" (_SFR_IO_ADDR(SPDR)) - : "memory" - ); -} - -static void __naked __used ucmb_handler_SENDMESSAGE(void) -{ - __asm__ __volatile__( -" push r16 \n" -" push r17 \n" -" push r18 \n" -" lds r16, ucmb_buf_ptr + 0 \n" -" lds r17, ucmb_buf_ptr + 1 \n" -" lds r30, ucmb_send_message_len + 0 \n" -" lds r31, ucmb_send_message_len + 1 \n" -" cp r16, r30 \n" -" cpc r17, r31 \n" -" brsh 1f ; This is the trailing byte \n" -" movw r30, r16 \n" -" subi r30, lo8(-(ucmb_buf)) \n" -" sbci r31, hi8(-(ucmb_buf)) \n" -" ld r18, Z \n" -" out %[_SPDR], r18 \n" -"1: \n" -" subi r16, lo8(-1) \n" -" sbci r17, hi8(-1) \n" -" sts ucmb_buf_ptr + 0, r16 \n" -" sts ucmb_buf_ptr + 1, r17 \n" -" lds r30, ucmb_send_message_len + 0 \n" -" lds r31, ucmb_send_message_len + 1 \n" -" subi r30, lo8(-1) \n" -" sbci r31, hi8(-1) \n" -" cp r16, r30 \n" -" cpc r17, r31 \n" -" brne st_sendmessage_out \n" -" ; Message + trailing byte processed. Retrieve status. \n" -" clr r18 \n" -" sts ucmb_buf_ptr + 0, r18 \n" -" sts ucmb_buf_ptr + 1, r18 \n" -" ldi r18, lo8(gs(ucmb_handler_RETRSTATUS)) \n" -" sts ucmb_interrupt_handler + 0, r18 \n" -" ldi r18, hi8(gs(ucmb_handler_RETRSTATUS)) \n" -" sts ucmb_interrupt_handler + 1, r18 \n" -"st_sendmessage_out: \n" -" pop r18 \n" -" pop r17 \n" -" pop r16 \n" -UCMB_IRQ_EPILOGUE /* reti */ - : /* none */ - : [_SPDR] "M" (_SFR_IO_ADDR(SPDR)) - : "memory" - ); -} - -static void __naked __used ucmb_handler_RETRSTATUS(void) -{ - __asm__ __volatile__( -" push r16 \n" -/*" push r17 \n"*/ -" push r18 \n" -" in r18, %[_SPDR] \n" -" lds r16, ucmb_buf_ptr + 0 \n" -" mov r30, r16 \n" -" clr r31 \n" -" subi r30, lo8(-(status_buf)) \n" -" sbci r31, hi8(-(status_buf)) \n" -" st Z, r18 \n" -" subi r16, -1 \n" -" sts ucmb_buf_ptr + 0, r16 \n" -" cpi r16, %[sizeof_ucmb_status] \n" -" brne st_retrstatus_out \n" -" ; Completely received the status \n" -" clr r16 \n" -" sts ucmb_buf_ptr + 0, r16 \n" -" ; Switch back to listening state... \n" -" ldi r18, lo8(gs(ucmb_handler_LISTEN)) \n" -" sts ucmb_interrupt_handler + 0, r18 \n" -" ldi r18, hi8(gs(ucmb_handler_LISTEN)) \n" -" sts ucmb_interrupt_handler + 1, r18 \n" -" ; Check status-report magic value \n" -" lds r30, (status_buf + %[offsetof_status_magic] + 0) \n" -" lds r31, (status_buf + %[offsetof_status_magic] + 1) \n" -" ldi r18, hi8(%[_UCMB_MAGIC]) \n" -" cpi r30, lo8(%[_UCMB_MAGIC]) \n" -" cpc r31, r18 \n" -" brne invalid_status_magic \n" -" ; Check status-report error code \n" -" lds r30, (status_buf + %[offsetof_status_code] + 0) \n" -" lds r31, (status_buf + %[offsetof_status_code] + 1) \n" -" ldi r18, hi8(%[_UCMB_STAT_OK]) \n" -" cpi r30, lo8(%[_UCMB_STAT_OK]) \n" -" cpc r31, r18 \n" -" brne faulty_status_code \n" -"st_retrstatus_out: \n" -" pop r18 \n" -/*" pop r17 \n"*/ -" pop r16 \n" -UCMB_IRQ_EPILOGUE /* reti */ -" \n" -"invalid_status_magic: \n" -"faulty_status_code: \n" -" ; Branch to the C error handler \n" -" ; The handler does not return, so we don't need to \n" -" ; push/pop the registers. \n" -" clr __zero_reg__ \n" -" rjmp ucmb_received_faulty_status \n" - : /* none */ - : [sizeof_ucmb_status] "M" (sizeof(struct ucmb_status)) - , [offsetof_status_magic] "M" (offsetof(struct ucmb_status, magic)) - , [offsetof_status_code] "M" (offsetof(struct ucmb_status, code)) - , [_SPDR] "M" (_SFR_IO_ADDR(SPDR)) - , [_UCMB_MAGIC] "i" (UCMB_MAGIC) - , [_UCMB_STAT_OK] "i" (UCMB_STAT_OK) - : "memory" - ); -} - -/* We received a status report with an error condition. - * This is called from assembly code. The function does not return. */ -static void __used __noret ucmb_received_faulty_status(void) -{ - /* The master sent us a status report with an error code. - * Something's wrong with us. Print a status message and - * get caught by the watchdog, yummy. - */ - - cli(); - wdt_disable(); - wdt_enable(WDTO_15MS); - ucmb_errorlog("UCMB: Received faulty status report. Triggering reset."); - while (1) { - /* "It's Coming Right For Us!" */ - } -} - -void ucmb_work(void) -{ - struct ucmb_message_hdr *hdr; - struct ucmb_message_footer *footer; - uint16_t payload_len; - - if (!ucmb_received_message) - return; - - hdr = (struct ucmb_message_hdr *)ucmb_buf; - payload_len = hdr->len; - - status_buf.magic = UCMB_MAGIC; - status_buf.code = UCMB_STAT_OK; - if (unlikely(ucmb_buf_ptr > sizeof(ucmb_buf))) { - /* Message is way too big and was truncated. */ - status_buf.code = UCMB_STAT_E2BIG; - } else { - footer = (struct ucmb_message_footer *)( - ucmb_buf + sizeof(struct ucmb_message_hdr) + - payload_len); - if (ucmb_calc_msg_buffer_crc() != footer->crc) - status_buf.code = UCMB_STAT_ECRC; - } - ucmb_interrupt_handler = ucmb_handler_SENDSTATUS; - ucmb_buf_ptr = 0; - /* Send the first byte */ - SPDR = ((uint8_t *)&status_buf)[ucmb_buf_ptr]; - ucmb_buf_ptr++; - - if (unlikely(status_buf.code != UCMB_STAT_OK)) - goto out; /* Corrupt message. Don't pass it to user code. */ - - ucmb_send_message_len = ucmb_rx_message( - ucmb_buf + sizeof(struct ucmb_message_hdr), - payload_len); - if (ucmb_send_message_len) { - footer = (struct ucmb_message_footer *)( - ucmb_buf + sizeof(struct ucmb_message_hdr) + - ucmb_send_message_len); - - hdr->magic = UCMB_MAGIC; - hdr->len = ucmb_send_message_len; - footer->crc = ucmb_calc_msg_buffer_crc(); - - ucmb_send_message_len += sizeof(struct ucmb_message_hdr) + - sizeof(struct ucmb_message_footer); - } - -out: - ucmb_received_message = 0; - mb(); - /* Re-enable SPI */ - SPCR |= (1 << SPIE); -} - -void ucmb_init(void) -{ - ucmb_interrupt_handler = ucmb_handler_LISTEN; - - /* SPI slave mode 0 with IRQ enabled. */ - DDRB |= (1 << 6/*MISO*/); - DDRB &= ~((1 << 7/*SCK*/) | (1 << 5/*MOSI*/) | (1 << 4/*SS*/)); - SPCR = (1 << SPE) | (1 << SPIE) /*| (1 << CPOL) | (1 << CPHA)*/; - (void)SPSR; /* clear state */ - (void)SPDR; /* clear state */ -} diff --git a/utils/ucmb/microcontroller_examples/atmel_avr8_optimized/ucmb.h b/utils/ucmb/microcontroller_examples/atmel_avr8_optimized/ucmb.h deleted file mode 100644 index 06853d5fa..000000000 --- a/utils/ucmb/microcontroller_examples/atmel_avr8_optimized/ucmb.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef UCMB_AVR8_H_ -#define UCMB_AVR8_H_ - -#include - - -/* Max length of the message payload. */ -#define UCMB_MAX_MSG_LEN (128 * 64 / 8 + 16) - -/* Error logs: If you want UCMB error log messages, define - * ucmb_errorlog(message_string_literal) - * somewhere. If you don't define it, UCMB will be compiled - * without error messages. */ - -/* ucmb_rx_message - Message receive callback. - * Define this elsewhere. It's called on successful retrieval - * of a new message. - * If a reply message has to be transferred after this one, put the - * message payload into the "payload" buffer and return the number - * of bytes to transmit. If no reply message is needed, return 0. - * Note that the "payload" buffer always has a size of UCMB_MAX_MSG_LEN. - * This function is called with interrupts enabled. - */ -extern uint16_t ucmb_rx_message(uint8_t *payload, - uint16_t payload_length); - -/* ucmb_work - Frequently call this from the mainloop. - * Must not be called from interrupt context. - * Must not be called with interrupts disabled. - */ -void ucmb_work(void); - -/* Initialize the UCMB subsystem. */ -void ucmb_init(void); - -#endif /* UCMB_AVR8_H_ */ -- 2.11.0