diff --git a/src/systemcmds/mtd/mtd.c b/src/systemcmds/mtd/mtd.c index 1379ceae17..82c1e289ac 100644 --- a/src/systemcmds/mtd/mtd.c +++ b/src/systemcmds/mtd/mtd.c @@ -40,6 +40,8 @@ */ #include +#include +#include #include #include @@ -62,7 +64,6 @@ #include "systemlib/px4_macros.h" #include "systemlib/systemlib.h" #include "systemlib/param/param.h" -#include "systemlib/err.h" #include @@ -70,10 +71,11 @@ __EXPORT int mtd_main(int argc, char *argv[]); #ifndef CONFIG_MTD -/* create a fake command with decent warnx to not confuse users */ +/* create a fake command with decent warning to not confuse users */ int mtd_main(int argc, char *argv[]) { - errx(1, "MTD not enabled, skipping."); + PX4_WARN("MTD not enabled, skipping."); + return 1; } #else @@ -86,7 +88,7 @@ int mtd_main(int argc, char *argv[]) #ifdef CONFIG_MTD_RAMTRON -static void ramtron_attach(void); +static int ramtron_attach(void); #else #ifndef PX4_I2C_BUS_MTD @@ -98,14 +100,13 @@ static void ramtron_attach(void); #endif -static void at24xxx_attach(void); +static int at24xxx_attach(void); #endif -static void mtd_start(char *partition_names[], unsigned n_partitions); -static void mtd_test(void); -static void mtd_erase(char *partition_names[], unsigned n_partitions); -static void mtd_readtest(char *partition_names[], unsigned n_partitions); -static void mtd_rwtest(char *partition_names[], unsigned n_partitions); -static void mtd_print_info(void); +static int mtd_start(char *partition_names[], unsigned n_partitions); +static int mtd_erase(char *partition_names[], unsigned n_partitions); +static int mtd_readtest(char *partition_names[], unsigned n_partitions); +static int mtd_rwtest(char *partition_names[], unsigned n_partitions); +static int mtd_print_info(void); static int mtd_get_geometry(unsigned long *blocksize, unsigned long *erasesize, unsigned long *neraseblocks, unsigned *blkpererase, unsigned *nblocks, unsigned *partsize, unsigned n_partitions); @@ -118,15 +119,32 @@ static unsigned n_partitions_current = 0; static char *partition_names_default[] = MTD_PARTITION_TABLE; static const int n_partitions_default = arraySize(partition_names_default); -static void +static int mtd_status(void) { if (!attached) { - errx(1, "MTD driver not started"); + PX4_ERR("MTD driver not started"); + return 1; } - mtd_print_info(); - exit(0); + return mtd_print_info(); +} + +static void print_usage(void) +{ + PRINT_MODULE_DESCRIPTION("Utility to mount and test partitions (based on FRAM/EEPROM storage as defined by the board)"); + + PRINT_MODULE_USAGE_NAME("mtd", "command"); + PRINT_MODULE_USAGE_COMMAND_DESCR("status", "Print status information"); + + PRINT_MODULE_USAGE_COMMAND_DESCR("start", "Mount partitions"); + PRINT_MODULE_USAGE_COMMAND_DESCR("readtest", "Perform read test"); + PRINT_MODULE_USAGE_COMMAND_DESCR("rwtest", "Perform read-write test"); + PRINT_MODULE_USAGE_COMMAND_DESCR("erase", "Erase partition(s)"); + + PRINT_MODULE_USAGE_PARAM_COMMENT("The commands 'start', 'readtest', 'rwtest' and 'erase' have an optional parameter:"); + PRINT_MODULE_USAGE_ARG(" [ ...]", + "Partition names (eg. /fs/mtd_params), use system default if not provided", true); } int mtd_main(int argc, char *argv[]) @@ -136,50 +154,47 @@ int mtd_main(int argc, char *argv[]) /* start mapping according to user request */ if (argc >= 3) { - mtd_start(argv + 2, argc - 2); + return mtd_start(argv + 2, argc - 2); } else { - mtd_start(partition_names_default, n_partitions_default); + return mtd_start(partition_names_default, n_partitions_default); } } - if (!strcmp(argv[1], "test")) { - mtd_test(); - } - if (!strcmp(argv[1], "readtest")) { if (argc >= 3) { - mtd_readtest(argv + 2, argc - 2); + return mtd_readtest(argv + 2, argc - 2); } else { - mtd_readtest(partition_names_default, n_partitions_default); + return mtd_readtest(partition_names_default, n_partitions_default); } } if (!strcmp(argv[1], "rwtest")) { if (argc >= 3) { - mtd_rwtest(argv + 2, argc - 2); + return mtd_rwtest(argv + 2, argc - 2); } else { - mtd_rwtest(partition_names_default, n_partitions_default); + return mtd_rwtest(partition_names_default, n_partitions_default); } } if (!strcmp(argv[1], "status")) { - mtd_status(); + return mtd_status(); } if (!strcmp(argv[1], "erase")) { if (argc >= 3) { - mtd_erase(argv + 2, argc - 2); + return mtd_erase(argv + 2, argc - 2); } else { - mtd_erase(partition_names_default, n_partitions_default); + return mtd_erase(partition_names_default, n_partitions_default); } } } - errx(1, "expected a command, try 'start', 'erase', 'status', 'readtest', 'rwtest' or 'test'"); + print_usage(); + return 1; } struct mtd_dev_s *ramtron_initialize(FAR struct spi_dev_s *dev); @@ -187,7 +202,7 @@ struct mtd_dev_s *mtd_partition(FAR struct mtd_dev_s *mtd, off_t firstblock, off_t nblocks); #ifdef CONFIG_MTD_RAMTRON -static void +static int ramtron_attach(void) { /* initialize the right spi */ @@ -200,7 +215,8 @@ ramtron_attach(void) SPI_SELECT(spi, SPIDEV_FLASH, false); if (spi == NULL) { - errx(1, "failed to locate spi bus"); + PX4_ERR("failed to locate spi bus"); + return 1; } /* start the RAMTRON driver, attempt 5 times */ @@ -210,7 +226,7 @@ ramtron_attach(void) if (mtd_dev) { /* abort on first valid result */ if (i > 0) { - warnx("warning: mtd needed %d attempts to attach", i + 1); + PX4_WARN("mtd needed %d attempts to attach", i + 1); } break; @@ -219,30 +235,33 @@ ramtron_attach(void) /* if last attempt is still unsuccessful, abort */ if (mtd_dev == NULL) { - errx(1, "failed to initialize mtd driver"); + PX4_ERR("failed to initialize mtd driver"); + return 1; } int ret = mtd_dev->ioctl(mtd_dev, MTDIOC_SETSPEED, (unsigned long)10 * 1000 * 1000); if (ret != OK) { - // FIXME: From the previous warnx call, it looked like this should have been an errx instead. Tried - // that but setting the bug speed does fail all the time. Which was then exiting and the board would - // not run correctly. So changed to warnx. - warnx("failed to set bus speed"); + // FIXME: From the previous warning call, it looked like this should have been fatal error instead. Tried + // that but setting the bus speed does fail all the time. Which was then exiting and the board would + // not run correctly. So changed to PX4_WARN. + PX4_WARN("failed to set bus speed"); } attached = true; + return 0; } #else -static void +static int at24xxx_attach(void) { /* find the right I2C */ struct i2c_master_s *i2c = px4_i2cbus_initialize(PX4_I2C_BUS_MTD); if (i2c == NULL) { - errx(1, "failed to locate I2C bus"); + PX4_ERR("failed to locate I2C bus"); + return 1; } /* start the MTD driver, attempt 5 times */ @@ -252,7 +271,7 @@ at24xxx_attach(void) if (mtd_dev) { /* abort on first valid result */ if (i > 0) { - warnx("warning: EEPROM needed %d attempts to attach", i + 1); + PX4_WARN("EEPROM needed %d attempts to attach", i + 1); } break; @@ -261,33 +280,40 @@ at24xxx_attach(void) /* if last attempt is still unsuccessful, abort */ if (mtd_dev == NULL) { - errx(1, "failed to initialize EEPROM driver"); + PX4_ERR("failed to initialize EEPROM driver"); + return 1; } attached = true; + return 0; } #endif -static void +static int mtd_start(char *partition_names[], unsigned n_partitions) { int ret; if (started) { - errx(1, "mtd already mounted"); + PX4_ERR("mtd already mounted"); + return 1; } if (!attached) { #ifdef CONFIG_MTD_RAMTRON - ramtron_attach(); + ret = ramtron_attach(); #else - at24xxx_attach(); + ret = at24xxx_attach(); #endif + + if (ret != 0) { + return ret; + } } if (!mtd_dev) { - warnx("ERROR: Failed to create RAMTRON FRAM MTD instance"); - exit(1); + PX4_ERR("Failed to create RAMTRON FRAM MTD instance"); + return 1; } unsigned long blocksize, erasesize, neraseblocks; @@ -296,7 +322,7 @@ mtd_start(char *partition_names[], unsigned n_partitions) ret = mtd_get_geometry(&blocksize, &erasesize, &neraseblocks, &blkpererase, &nblocks, &partsize, n_partitions); if (ret) { - exit(3); + return ret; } /* Now create MTD FLASH partitions */ @@ -314,9 +340,9 @@ mtd_start(char *partition_names[], unsigned n_partitions) part[i] = mtd_partition(mtd_dev, offset, nblocks); if (!part[i]) { - warnx("ERROR: mtd_partition failed. offset=%lu nblocks=%lu", - (unsigned long)offset, (unsigned long)nblocks); - exit(4); + PX4_ERR("mtd_partition failed. offset=%lu nblocks=%lu", + (unsigned long)offset, (unsigned long)nblocks); + return 1; } /* Initialize to provide an FTL block driver on the MTD FLASH interface */ @@ -326,8 +352,8 @@ mtd_start(char *partition_names[], unsigned n_partitions) ret = ftl_initialize(i, part[i]); if (ret < 0) { - warnx("ERROR: ftl_initialize %s failed: %d", blockname, ret); - exit(5); + PX4_ERR("ftl_initialize %s failed: %d", blockname, ret); + return 1; } /* Now create a character device on the block device */ @@ -335,15 +361,15 @@ mtd_start(char *partition_names[], unsigned n_partitions) ret = bchdev_register(blockname, partition_names[i], false); if (ret < 0) { - warnx("ERROR: bchdev_register %s failed: %d", partition_names[i], ret); - exit(6); + PX4_ERR("bchdev_register %s failed: %d", partition_names[i], ret); + return 1; } } n_partitions_current = n_partitions; started = true; - exit(0); + return 0; } int mtd_get_geometry(unsigned long *blocksize, unsigned long *erasesize, unsigned long *neraseblocks, @@ -356,7 +382,7 @@ int mtd_get_geometry(unsigned long *blocksize, unsigned long *erasesize, unsigne int ret = mtd_dev->ioctl(mtd_dev, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo)); if (ret < 0) { - warnx("ERROR: mtd->ioctl failed: %d", ret); + PX4_ERR("mtd->ioctl failed: %d", ret); return ret; } @@ -388,16 +414,17 @@ static ssize_t mtd_get_partition_size(void) n_partitions_current); if (ret != OK) { - errx(1, "Failed to get geometry"); + PX4_ERR("Failed to get geometry"); + return 0; } return partsize; } -void mtd_print_info(void) +int mtd_print_info(void) { if (!attached) { - exit(1); + return 1; } unsigned long blocksize, erasesize, neraseblocks; @@ -407,10 +434,10 @@ void mtd_print_info(void) n_partitions_current); if (ret) { - exit(3); + return ret; } - warnx("Flash Geometry:"); + PX4_INFO("Flash Geometry:"); printf(" blocksize: %lu\n", blocksize); printf(" erasesize: %lu\n", erasesize); @@ -419,16 +446,10 @@ void mtd_print_info(void) printf(" Partition size: %u Blocks (%u bytes)\n", nblocks, partsize); printf(" TOTAL SIZE: %u KiB\n", neraseblocks * erasesize / 1024); + return 0; } -void -mtd_test(void) -{ - warnx("This test routine does not test anything yet!"); - exit(1); -} - -void +int mtd_erase(char *partition_names[], unsigned n_partitions) { uint8_t v[64]; @@ -440,7 +461,8 @@ mtd_erase(char *partition_names[], unsigned n_partitions) int fd = open(partition_names[i], O_WRONLY); if (fd == -1) { - errx(1, "Failed to open partition"); + PX4_ERR("Failed to open partition"); + return 1; } while (write(fd, v, sizeof(v)) == sizeof(v)) { @@ -451,7 +473,7 @@ mtd_erase(char *partition_names[], unsigned n_partitions) close(fd); } - exit(0); + return 0; } /* @@ -459,11 +481,15 @@ mtd_erase(char *partition_names[], unsigned n_partitions) responding on the bus. It relies on the driver returning an error on bad reads (the ramtron driver does return an error) */ -void +int mtd_readtest(char *partition_names[], unsigned n_partitions) { ssize_t expected_size = mtd_get_partition_size(); + if (expected_size == 0) { + return 1; + } + uint8_t v[128]; for (uint8_t i = 0; i < n_partitions; i++) { @@ -472,7 +498,8 @@ mtd_readtest(char *partition_names[], unsigned n_partitions) int fd = open(partition_names[i], O_RDONLY); if (fd == -1) { - errx(1, "Failed to open partition"); + PX4_ERR("Failed to open partition"); + return 1; } while (read(fd, v, sizeof(v)) == sizeof(v)) { @@ -480,14 +507,15 @@ mtd_readtest(char *partition_names[], unsigned n_partitions) } if (count != expected_size) { - errx(1, "Failed to read partition - got %u/%u bytes", count, expected_size); + PX4_ERR("Failed to read partition - got %u/%u bytes", count, expected_size); + return 1; } close(fd); } printf("readtest OK\n"); - exit(0); + return 0; } /* @@ -496,11 +524,15 @@ mtd_readtest(char *partition_names[], unsigned n_partitions) blocks and writes the data back, then reads it again, failing if the data isn't the same */ -void +int mtd_rwtest(char *partition_names[], unsigned n_partitions) { ssize_t expected_size = mtd_get_partition_size(); + if (expected_size == 0) { + return 1; + } + uint8_t v[128], v2[128]; for (uint8_t i = 0; i < n_partitions; i++) { @@ -510,44 +542,51 @@ mtd_rwtest(char *partition_names[], unsigned n_partitions) int fd = open(partition_names[i], O_RDWR); if (fd == -1) { - errx(1, "Failed to open partition"); + PX4_ERR("Failed to open partition"); + return 1; } while (read(fd, v, sizeof(v)) == sizeof(v)) { count += sizeof(v); if (lseek(fd, offset, SEEK_SET) != offset) { - errx(1, "seek failed"); + PX4_ERR("seek failed"); + return 1; } if (write(fd, v, sizeof(v)) != sizeof(v)) { - errx(1, "write failed"); + PX4_ERR("write failed"); + return 1; } if (lseek(fd, offset, SEEK_SET) != offset) { - errx(1, "seek failed"); + PX4_ERR("seek failed"); + return 1; } if (read(fd, v2, sizeof(v2)) != sizeof(v2)) { - errx(1, "read failed"); + PX4_ERR("read failed"); + return 1; } if (memcmp(v, v2, sizeof(v2)) != 0) { - errx(1, "memcmp failed"); + PX4_ERR("memcmp failed"); + return 1; } offset += sizeof(v); } if (count != expected_size) { - errx(1, "Failed to read partition - got %u/%u bytes", count, expected_size); + PX4_ERR("Failed to read partition - got %u/%u bytes", count, expected_size); + return 1; } close(fd); } printf("rwtest OK\n"); - exit(0); + return 0; } #endif