From be40d3b2607e903b05543c6706ef75146d61574e Mon Sep 17 00:00:00 2001 From: Shunichi Wakabayashi <8855640+s-wakaba@users.noreply.github.com> Date: Tue, 20 Sep 2022 01:32:12 +0900 Subject: [PATCH 1/5] add extended parameter "disable_no_sc" for linuxspi programmer --- build.sh | 2 +- src/linuxspi.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 0b664807..bbb2f586 100755 --- a/build.sh +++ b/build.sh @@ -37,7 +37,7 @@ case "${ostype}" in # try to find out whether this is an Embedded Linux # platform (e.g. Raspberry Pi) machine=$(uname -m) - if expr "${machine}" : 'arm' >/dev/null + if expr "${machine}" : '^\(arm\|aarch\)' >/dev/null then extra_enable="${extra_enable} -D HAVE_LINUXGPIO=ON -D HAVE_LINUXSPI=ON" fi diff --git a/src/linuxspi.c b/src/linuxspi.c index 512755e3..2b708ae5 100644 --- a/src/linuxspi.c +++ b/src/linuxspi.c @@ -62,6 +62,16 @@ #define LINUXSPI "linuxspi" +/* + * Private data for this programmer. + */ +struct pdata +{ + int disable_no_cs; +}; + +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) + static int fd_spidev, fd_gpiochip, fd_linehandle; /** @@ -89,9 +99,16 @@ static int linuxspi_spi_duplex(const PROGRAMMER *pgm, const unsigned char *tx, u } static void linuxspi_setup(PROGRAMMER *pgm) { + if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { + avrdude_message(MSG_INFO, "%s: linuxspi_setup(): Out of memory allocating private data\n", + progname); + exit(1); + } + memset(pgm->cookie, 0, sizeof(struct pdata)); } static void linuxspi_teardown(PROGRAMMER* pgm) { + free(pgm->cookie); } static int linuxspi_reset_mcu(const PROGRAMMER *pgm, bool active) { @@ -162,11 +179,19 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) { return -1; } - uint32_t mode = SPI_MODE_0 | SPI_NO_CS; + uint32_t mode = SPI_MODE_0; + if (!PDATA(pgm)->disable_no_cs) { + mode |= SPI_NO_CS; + } ret = ioctl(fd_spidev, SPI_IOC_WR_MODE32, &mode); if (ret == -1) { + int ioctl_errno = errno; avrdude_message(MSG_INFO, "%s: error: Unable to set SPI mode %0X on %s\n", progname, mode, spidev); + if(ioctl_errno == EINVAL || !PDATA(pgm)->disable_no_cs) { + avrdude_message(MSG_NOTICE, "%s: Try \"-x disable_no_cs\" option\n", + progname); + } goto close_spidev; } fd_gpiochip = open(gpiochip, 0); @@ -378,6 +403,28 @@ static int linuxspi_parseexitspecs(PROGRAMMER *pgm, const char *sp) { return 0; } +static int linuxspi_parseextparams(const PROGRAMMER *pgm, const LISTID extparms) { + LNODEID ln; + const char *extended_param; + int rc = 0; + + for (ln = lfirst(extparms); ln; ln = lnext(ln)) { + extended_param = ldata(ln); + + if (strcmp(extended_param, "disable_no_cs") == 0) { + PDATA(pgm)->disable_no_cs = 1; + continue; + } + + avrdude_message(MSG_INFO, "%s: linuxspi_parseextparams(): " + "invalid extended parameter '%s'\n", + progname, extended_param); + rc = -1; + } + + return rc; +} + void linuxspi_initpgm(PROGRAMMER *pgm) { strcpy(pgm->type, LINUXSPI); @@ -400,6 +447,7 @@ void linuxspi_initpgm(PROGRAMMER *pgm) { pgm->setup = linuxspi_setup; pgm->teardown = linuxspi_teardown; pgm->parseexitspecs = linuxspi_parseexitspecs; + pgm->parseextparams = linuxspi_parseextparams; } const char linuxspi_desc[] = "SPI using Linux spidev driver"; From 93df07866a6eb92e126e7bd4e55f10f50e286008 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 22 Sep 2022 10:31:59 +0100 Subject: [PATCH 2/5] Inform user of -x disable_no_spi when needed (without -v) --- src/linuxspi.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/linuxspi.c b/src/linuxspi.c index 2b708ae5..8ba2a918 100644 --- a/src/linuxspi.c +++ b/src/linuxspi.c @@ -65,8 +65,7 @@ /* * Private data for this programmer. */ -struct pdata -{ +struct pdata { int disable_no_cs; }; @@ -99,12 +98,7 @@ static int linuxspi_spi_duplex(const PROGRAMMER *pgm, const unsigned char *tx, u } static void linuxspi_setup(PROGRAMMER *pgm) { - if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { - avrdude_message(MSG_INFO, "%s: linuxspi_setup(): Out of memory allocating private data\n", - progname); - exit(1); - } - memset(pgm->cookie, 0, sizeof(struct pdata)); + pgm->cookie = cfg_malloc("linuxspi_setup()", sizeof(struct pdata)); } static void linuxspi_teardown(PROGRAMMER* pgm) { @@ -180,18 +174,16 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) { } uint32_t mode = SPI_MODE_0; - if (!PDATA(pgm)->disable_no_cs) { + if (!PDATA(pgm)->disable_no_cs) mode |= SPI_NO_CS; - } + ret = ioctl(fd_spidev, SPI_IOC_WR_MODE32, &mode); if (ret == -1) { int ioctl_errno = errno; avrdude_message(MSG_INFO, "%s: error: Unable to set SPI mode %0X on %s\n", progname, mode, spidev); - if(ioctl_errno == EINVAL || !PDATA(pgm)->disable_no_cs) { - avrdude_message(MSG_NOTICE, "%s: Try \"-x disable_no_cs\" option\n", - progname); - } + if(ioctl_errno == EINVAL || !PDATA(pgm)->disable_no_cs) + avrdude_message(MSG_INFO, "%s: try -x disable_no_cs\n", progname); goto close_spidev; } fd_gpiochip = open(gpiochip, 0); From aa789d46620e112a76e1bfcc85ec493942cf74b8 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 22 Sep 2022 10:39:31 +0100 Subject: [PATCH 3/5] Change error messages in linuxspi.c to maintain single style --- src/linuxspi.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/linuxspi.c b/src/linuxspi.c index 8ba2a918..d3bbaf84 100644 --- a/src/linuxspi.c +++ b/src/linuxspi.c @@ -86,13 +86,13 @@ static int linuxspi_spi_duplex(const PROGRAMMER *pgm, const unsigned char *tx, u .rx_buf = (unsigned long)rx, .len = len, .delay_usecs = 1, - .speed_hz = 1.0 / pgm->bitclock, // seconds to Hz + .speed_hz = 1.0 / pgm->bitclock, .bits_per_word = 8, }; ret = ioctl(fd_spidev, SPI_IOC_MESSAGE(1), &tr); if (ret != len) - avrdude_message(MSG_INFO, "\n%s: error: Unable to send SPI message\n", progname); + avrdude_message(MSG_INFO, "\n%s: error, unable to send SPI message\n", progname); return (ret == -1) ? -1 : 0; } @@ -127,7 +127,7 @@ static int linuxspi_reset_mcu(const PROGRAMMER *pgm, bool active) { #endif if (ret == -1) { ret = -errno; - avrdude_message(MSG_INFO, "%s error: Unable to set GPIO line %d value\n", + avrdude_message(MSG_INFO, "%s: error, unable to set GPIO line %d value\n", progname, pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE); return ret; } @@ -137,8 +137,8 @@ static int linuxspi_reset_mcu(const PROGRAMMER *pgm, bool active) { static int linuxspi_open(PROGRAMMER *pgm, const char *pt) { const char *port_error = - "%s: error: Unknown port specification. " - "Please use the format /dev/spidev:/dev/gpiochip[:resetno]\n"; + "%s: error, unknown port specification; " + "please use the format /dev/spidev:/dev/gpiochip[:resetno]\n"; char port_default[] = "/dev/spidev0.0:/dev/gpiochip0"; char *spidev, *gpiochip, *reset_pin; char *port = cfg_strdup("linuxspi_open()", pt); @@ -169,7 +169,7 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) { strcpy(pgm->port, port); fd_spidev = open(pgm->port, O_RDWR); if (fd_spidev < 0) { - avrdude_message(MSG_INFO, "\n%s: error: Unable to open the spidev device %s", progname, pgm->port); + avrdude_message(MSG_INFO, "\n%s: error, unable to open the spidev device %s", progname, pgm->port); return -1; } @@ -180,7 +180,7 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) { ret = ioctl(fd_spidev, SPI_IOC_WR_MODE32, &mode); if (ret == -1) { int ioctl_errno = errno; - avrdude_message(MSG_INFO, "%s: error: Unable to set SPI mode %0X on %s\n", + avrdude_message(MSG_INFO, "%s: error, unable to set SPI mode %02X on %s\n", progname, mode, spidev); if(ioctl_errno == EINVAL || !PDATA(pgm)->disable_no_cs) avrdude_message(MSG_INFO, "%s: try -x disable_no_cs\n", progname); @@ -188,7 +188,7 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) { } fd_gpiochip = open(gpiochip, 0); if (fd_gpiochip < 0) { - avrdude_message(MSG_INFO, "\n%s error: Unable to open the gpiochip %s", progname, gpiochip); + avrdude_message(MSG_INFO, "\n%s: error, unable to open the gpiochip %s", progname, gpiochip); ret = -1; goto close_spidev; } @@ -223,7 +223,7 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) { #endif if (ret == -1) { ret = -errno; - avrdude_message(MSG_INFO, "%s error: Unable to get GPIO line %d\n", + avrdude_message(MSG_INFO, "%s: error, unable to get GPIO line %d\n", progname, pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE); goto close_gpiochip; } @@ -234,14 +234,13 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) { if (pgm->baudrate != 0) { avrdude_message(MSG_INFO, - "%s: obsolete use of -b option for bit clock; use -B \n", - progname); + "%s: obsolete use of -b option for bit clock; use -B \n", + progname); pgm->bitclock = 1.0 / pgm->baudrate; } if (pgm->bitclock == 0) { avrdude_message(MSG_NOTICE, - "%s: defaulting bit clock to 200 kHz\n", - progname); + "%s: defaulting bit clock to 200 kHz\n", progname); pgm->bitclock = 5E-6; // 200 kHz - 5 µs } @@ -289,7 +288,7 @@ static int linuxspi_initialize(const PROGRAMMER *pgm, const AVRPART *p) { if (p->prog_modes & PM_TPI) { /* We do not support TPI. This is a dedicated SPI thing */ - avrdude_message(MSG_INFO, "%s: error: Programmer " LINUXSPI " does not support TPI\n", progname); + avrdude_message(MSG_INFO, "%s: error, programmer " LINUXSPI " does not support TPI\n", progname); return -1; } @@ -303,7 +302,7 @@ static int linuxspi_initialize(const PROGRAMMER *pgm, const AVRPART *p) { } while(tries++ < 65); if (ret) - avrdude_message(MSG_INFO, "%s: error: AVR device not responding\n", progname); + avrdude_message(MSG_INFO, "%s: error, AVR device not responding\n", progname); return ret; } @@ -317,7 +316,7 @@ static int linuxspi_program_enable(const PROGRAMMER *pgm, const AVRPART *p) { unsigned char cmd[4], res[4]; if (!p->op[AVR_OP_PGM_ENABLE]) { - avrdude_message(MSG_INFO, "%s: error: program enable instruction not defined for part \"%s\"\n", progname, p->desc); + avrdude_message(MSG_INFO, "%s: error, program enable instruction not defined for part %s\n", progname, p->desc); return -1; } @@ -360,7 +359,7 @@ static int linuxspi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) { unsigned char cmd[4], res[4]; if (!p->op[AVR_OP_CHIP_ERASE]) { - avrdude_message(MSG_INFO, "%s: error: chip erase instruction not defined for part \"%s\"\n", progname, p->desc); + avrdude_message(MSG_INFO, "%s: error, chip erase instruction not defined for part %s\n", progname, p->desc); return -1; } From ca154f812f473caed51025409613c64dc1b7fcc2 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Fri, 23 Sep 2022 16:53:52 +0100 Subject: [PATCH 4/5] Improve error messaging in linuxspi.c --- src/linuxspi.c | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/linuxspi.c b/src/linuxspi.c index d3bbaf84..c7806081 100644 --- a/src/linuxspi.c +++ b/src/linuxspi.c @@ -90,11 +90,16 @@ static int linuxspi_spi_duplex(const PROGRAMMER *pgm, const unsigned char *tx, u .bits_per_word = 8, }; + errno = 0; ret = ioctl(fd_spidev, SPI_IOC_MESSAGE(1), &tr); - if (ret != len) - avrdude_message(MSG_INFO, "\n%s: error, unable to send SPI message\n", progname); + if (ret != len) { + avrdude_message(MSG_INFO, "\n%s: unable to send SPI message", progname); + if (errno) + avrdude_message(MSG_INFO, ". %s", strerror(errno)); + avrdude_message(MSG_INFO, "\n"); + } - return (ret == -1) ? -1 : 0; + return ret == -1? -1: 0; } static void linuxspi_setup(PROGRAMMER *pgm) { @@ -127,8 +132,8 @@ static int linuxspi_reset_mcu(const PROGRAMMER *pgm, bool active) { #endif if (ret == -1) { ret = -errno; - avrdude_message(MSG_INFO, "%s: error, unable to set GPIO line %d value\n", - progname, pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE); + avrdude_message(MSG_INFO, "%s: unable to set GPIO line %d value. %s\n", + progname, pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE, strerror(errno)); return ret; } @@ -169,7 +174,8 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) { strcpy(pgm->port, port); fd_spidev = open(pgm->port, O_RDWR); if (fd_spidev < 0) { - avrdude_message(MSG_INFO, "\n%s: error, unable to open the spidev device %s", progname, pgm->port); + avrdude_message(MSG_INFO, "\n%s: unable to open the spidev device %s. %s", + progname, pgm->port, strerror(errno)); return -1; } @@ -180,15 +186,16 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) { ret = ioctl(fd_spidev, SPI_IOC_WR_MODE32, &mode); if (ret == -1) { int ioctl_errno = errno; - avrdude_message(MSG_INFO, "%s: error, unable to set SPI mode %02X on %s\n", - progname, mode, spidev); - if(ioctl_errno == EINVAL || !PDATA(pgm)->disable_no_cs) + avrdude_message(MSG_INFO, "%s: unable to set SPI mode %02X on %s. %s\n", + progname, mode, spidev, strerror(errno)); + if(ioctl_errno == EINVAL && !PDATA(pgm)->disable_no_cs) avrdude_message(MSG_INFO, "%s: try -x disable_no_cs\n", progname); goto close_spidev; } fd_gpiochip = open(gpiochip, 0); if (fd_gpiochip < 0) { - avrdude_message(MSG_INFO, "\n%s: error, unable to open the gpiochip %s", progname, gpiochip); + avrdude_message(MSG_INFO, "\n%s: unable to open the gpiochip %s. %s\n", + progname, gpiochip, strerror(errno)); ret = -1; goto close_spidev; } @@ -223,8 +230,8 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) { #endif if (ret == -1) { ret = -errno; - avrdude_message(MSG_INFO, "%s: error, unable to get GPIO line %d\n", - progname, pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE); + avrdude_message(MSG_INFO, "%s: unable to get GPIO line %d. %s\n", + progname, pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE, strerror(errno)); goto close_gpiochip; } @@ -233,15 +240,15 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) { goto close_out; if (pgm->baudrate != 0) { - avrdude_message(MSG_INFO, - "%s: obsolete use of -b option for bit clock; use -B \n", - progname); + avrdude_message(MSG_INFO, + "%s: obsolete use of -b option for bit clock; use -B \n", + progname); pgm->bitclock = 1.0 / pgm->baudrate; } if (pgm->bitclock == 0) { - avrdude_message(MSG_NOTICE, - "%s: defaulting bit clock to 200 kHz\n", progname); - pgm->bitclock = 5E-6; // 200 kHz - 5 µs + avrdude_message(MSG_NOTICE, + "%s: defaulting bit clock to 200 kHz\n", progname); + pgm->bitclock = 5E-6; // 200 kHz - 5 µs } return 0; @@ -408,8 +415,7 @@ static int linuxspi_parseextparams(const PROGRAMMER *pgm, const LISTID extparms) } avrdude_message(MSG_INFO, "%s: linuxspi_parseextparams(): " - "invalid extended parameter '%s'\n", - progname, extended_param); + "invalid extended parameter '%s'\n", progname, extended_param); rc = -1; } From f17a012325348f797ece404c0104250c8e0e2e5d Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sat, 24 Sep 2022 00:16:55 +0100 Subject: [PATCH 5/5] Update documentation for linuxspi extended parameter disable_no_cs --- src/avrdude.1 | 8 ++++++++ src/doc/avrdude.texi | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/avrdude.1 b/src/avrdude.1 index 1920b583..69989f9e 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -1217,6 +1217,14 @@ specific. .Pp When not provided, driver/OS default value will be used. .El +.It Ar linuxspi +Extended parameter: +.Bl -tag -offset indent -width indent +.It Ar disable_no_cs +Ensures the programmer does not use the SPI_NO_CS bit for the SPI +driver. This parameter is useful for kernels that do not support +the CS line being managed outside the application. +.El .El .Sh FILES .Bl -tag -offset indent -width /dev/ppi0XXX diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 3bcade32..3826eefd 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -1111,6 +1111,16 @@ specific. When not provided, driver/OS default value will be used. @end table +@cindex @code{-x} linuxspi +@item linuxspi +Extended parameter: +@table @code +@item @samp{disable_no_cs} +Ensures the programmer does not use the SPI_NO_CS bit for the SPI +driver. This parameter is useful for kernels that do not support +the CS line being managed outside the application. +@end table + @end table @page