From e14834817f78a04b4d9b44a8373119dffd42c966 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Mar 2013 01:12:33 -0700 Subject: altos: Add SDCARD and FAT16 filesystem support This adds a fairly primitive FAT16 file system implementation along with support for SD cards. Signed-off-by: Keith Packard --- src/test/Makefile | 5 ++- src/test/ao_fat_test.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 src/test/ao_fat_test.c (limited to 'src/test') diff --git a/src/test/Makefile b/src/test/Makefile index fccc7937..96170cc1 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -2,7 +2,7 @@ vpath % ..:../core:../drivers:../util:../micropeak PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \ ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test ao_fec_test \ - ao_aprs_test ao_micropeak_test + ao_aprs_test ao_micropeak_test ao_fat_test INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h @@ -64,3 +64,6 @@ check: ao_fec_test ao_flight_test ao_flight_test_baro run-tests ao_micropeak_test: ao_micropeak_test.c ao_microflight.c ao_kalman.h cc $(CFLAGS) -o $@ ao_micropeak_test.c -lm + +ao_fat_test: ao_fat_test.c ao_fat.c ao_bufio.c + cc $(CFLAGS) -o $@ ao_fat_test.c diff --git a/src/test/ao_fat_test.c b/src/test/ao_fat_test.c new file mode 100644 index 00000000..22ac03ad --- /dev/null +++ b/src/test/ao_fat_test.c @@ -0,0 +1,118 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define AO_FAT_TEST + +void +ao_mutex_get(uint8_t *mutex) +{ +} + +void +ao_mutex_put(uint8_t *mutex) +{ +} + +void +ao_panic(uint8_t panic) +{ + printf ("panic %d\n", panic); + exit(1); +} + +#define AO_PANIC_BUFIO 15 + +#define ao_cmd_success 0 + +uint8_t ao_cmd_status; +uint32_t ao_cmd_lex_u32; + +void +ao_cmd_decimal() +{ +} + +#define ao_cmd_register(x) + +struct ao_cmds { + void (*func)(void); + const char *help; +}; + +int fs_fd; + +uint8_t +ao_sdcard_read_block(uint32_t block, uint8_t *data) +{ + lseek(fs_fd, block * 512, 0); + return read(fs_fd, data, 512) == 512; +} + +uint8_t +ao_sdcard_write_block(uint32_t block, uint8_t *data) +{ + lseek(fs_fd, block * 512, 0); + return write(fs_fd, data, 512) == 512; +} + +void +ao_sdcard_init(void) +{ + fs_fd = open("fat.fs", 2); +} + +#include "ao_bufio.c" +#include "ao_fat.c" + +int +main(int argc, char **argv) +{ + uint8_t data[15]; + int len; + ao_fat_init(); + ao_fat_test(); + if (ao_fat_open("DATALOG TXT")) { + printf ("DATALOG.TXT\n"); + while ((len = ao_fat_read(data, sizeof (data))) > 0) { + write(1, data, len); + } + ao_fat_close(); +// ao_fat_unlink("DATALOG TXT"); + } + if (ao_fat_open("NEWFILE TXT")) { + printf ("NEWFILE.TXT\n"); + while ((len = ao_fat_read(data, sizeof (data))) > 0) { + write(1, data, len); + } + ao_fat_close(); + } + if (ao_fat_creat ("NEWFILE TXT")) { + for (len = 0; len < 4095; len++) + ao_fat_write((uint8_t *) "hello, world!\n", 14); + ao_fat_close(); + } + return 0; +} -- cgit v1.2.3 From c7b606e93a4e4fbd2c0e883352ed74619ee24cf7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Mar 2013 16:05:24 -0700 Subject: altos: Clean up fat driver API. Improve fat test Make FAT api provide reasonable error return values, change the tests to write and then read a pile of files, checking that the contents are correct (using md5sum). Signed-off-by: Keith Packard --- src/drivers/ao_fat.c | 602 +++++++++++++++++++++++++++++++++---------------- src/drivers/ao_fat.h | 45 +++- src/test/Makefile | 2 +- src/test/ao_fat_test.c | 310 +++++++++++++++++++++++-- 4 files changed, 732 insertions(+), 227 deletions(-) (limited to 'src/test') diff --git a/src/drivers/ao_fat.c b/src/drivers/ao_fat.c index a1476168..c0412380 100644 --- a/src/drivers/ao_fat.c +++ b/src/drivers/ao_fat.c @@ -22,11 +22,17 @@ #include "ao_fat.h" #include "ao_bufio.h" -/* Partition information, block numbers */ +/* Partition information, sector numbers */ static uint8_t partition_type; static uint32_t partition_start, partition_end; +#define SECTOR_SIZE 512 +#define SECTOR_MASK (SECTOR_SIZE - 1) +#define SECTOR_SHIFT 9 + +#define DIRENT_SIZE 32 + /* File system parameters */ static uint8_t sectors_per_cluster; static uint32_t bytes_per_cluster; @@ -34,10 +40,15 @@ static uint16_t reserved_sector_count; static uint8_t number_fat; static uint16_t root_entries; static uint16_t sectors_per_fat; +static uint16_t number_cluster; static uint32_t fat_start; static uint32_t root_start; static uint32_t data_start; +static uint16_t first_free_cluster; +/* + * Deal with LSB FAT data structures + */ static uint32_t get_u32(uint8_t *base) { @@ -72,32 +83,32 @@ put_u16(uint8_t *base, uint16_t value) static uint8_t ao_fat_cluster_valid(uint16_t cluster) { - return (2 <= cluster && cluster < 0xfff0); + return (2 <= cluster && cluster < number_cluster); } -/* Start using a block */ +/* Start using a sector */ static uint8_t * -ao_fat_block_get(uint32_t block) +ao_fat_sector_get(uint32_t sector) { - block += partition_start; - if (block >= partition_end) + sector += partition_start; + if (sector >= partition_end) return NULL; - return ao_bufio_get(block); + return ao_bufio_get(sector); } -/* Finish using a block, 'w' is 1 if modified */ -#define ao_fat_block_put(b,w) ao_bufio_put(b,w) +/* Finish using a sector, 'w' is 1 if modified */ +#define ao_fat_sector_put(b,w) ao_bufio_put(b,w) /* Start using a root directory entry */ static uint8_t * ao_fat_root_get(uint16_t e) { - uint32_t byte = e * 0x20; - uint32_t sector = byte >> 9; - uint16_t offset = byte & 0x1ff; + uint32_t byte = e * DIRENT_SIZE; + uint32_t sector = byte >> SECTOR_SHIFT; + uint16_t offset = byte & SECTOR_MASK; uint8_t *buf; - buf = ao_fat_block_get(root_start + sector); + buf = ao_fat_sector_get(root_start + sector); if (!buf) return NULL; return buf + offset; @@ -107,10 +118,10 @@ ao_fat_root_get(uint16_t e) static void ao_fat_root_put(uint8_t *root, uint16_t e, uint8_t write) { - uint16_t offset = ((e * 0x20) & 0x1ff); + uint16_t offset = ((e * DIRENT_SIZE) & SECTOR_MASK); uint8_t *buf = root - offset; - ao_fat_block_put(buf, write); + ao_fat_sector_put(buf, write); } /* Get the next cluster entry in the chain */ @@ -125,17 +136,20 @@ ao_fat_entry_read(uint16_t cluster) if (!ao_fat_cluster_valid(cluster)) return 0xfff7; - cluster -= 2; - sector = cluster >> 8; - offset = (cluster << 1) & 0x1ff; - buf = ao_fat_block_get(fat_start + sector); +// cluster -= 2; + sector = cluster >> (SECTOR_SHIFT - 1); + offset = (cluster << 1) & SECTOR_MASK; + buf = ao_fat_sector_get(fat_start + sector); if (!buf) return 0; - ret = buf[offset] | (buf[offset+1] << 8); - ao_fat_block_put(buf, 0); + ret = get_u16(buf + offset); + ao_fat_sector_put(buf, 0); return ret; } +/* Replace the referenced cluster entry in the chain with + * 'new_value'. Return the previous value. + */ static uint16_t ao_fat_entry_replace(uint16_t cluster, uint16_t new_value) { @@ -148,33 +162,50 @@ ao_fat_entry_replace(uint16_t cluster, uint16_t new_value) if (!ao_fat_cluster_valid(cluster)) return 0; - cluster -= 2; - sector = cluster >> 8; - offset = (cluster << 1) & 0x1ff; - buf = ao_fat_block_get(fat_start + sector); +// cluster -= 2; + sector = cluster >> (SECTOR_SHIFT - 1); + offset = (cluster << 1) & SECTOR_MASK; + buf = ao_fat_sector_get(fat_start + sector); if (!buf) return 0; ret = get_u16(buf + offset); put_u16(buf + offset, new_value); - ao_fat_block_put(buf, 1); + ao_fat_sector_put(buf, 1); + + /* + * Keep the other FATs in sync + */ for (other_fats = 1; other_fats < number_fat; other_fats++) { - buf = ao_fat_block_get(fat_start + other_fats * sectors_per_fat); + buf = ao_fat_sector_get(fat_start + other_fats * sectors_per_fat + sector); if (buf) { put_u16(buf + offset, new_value); - ao_fat_block_put(buf, 1); + ao_fat_sector_put(buf, 1); } } return ret; } +/* + * Walk a cluster chain and mark + * all of them as free + */ static void -ao_fat_clear_cluster_chain(uint16_t cluster) +ao_fat_free_cluster_chain(uint16_t cluster) { - while (ao_fat_cluster_valid(cluster)) + while (ao_fat_cluster_valid(cluster)) { + if (cluster < first_free_cluster) + first_free_cluster = cluster; cluster = ao_fat_entry_replace(cluster, 0x0000); + } } +/* + * ao_fat_cluster_seek + * + * Walk a cluster chain the specified distance and return what we find + * there. If distance is zero, return the provided cluster. + */ static uint16_t ao_fat_cluster_seek(uint16_t cluster, uint16_t distance) { @@ -187,16 +218,39 @@ ao_fat_cluster_seek(uint16_t cluster, uint16_t distance) return cluster; } +/* + * ao_fat_sector_seek + * + * The basic file system operation -- map a file sector number to a + * partition sector number. Done by computing the cluster number and + * then walking that many clusters from the first cluster, then + * adding the sector offset from the start of the cluster. Returns + * 0xffffffff if we walk off the end of the file or the cluster chain + * is damaged somehow + */ static uint32_t ao_fat_sector_seek(uint16_t cluster, uint32_t sector) { - cluster = ao_fat_cluster_seek(cluster, sector / sectors_per_cluster); + uint16_t distance; + uint16_t offset; + + distance = sector / sectors_per_cluster; + offset = sector % sectors_per_cluster; + + cluster = ao_fat_cluster_seek(cluster, distance); + if (!ao_fat_cluster_valid(cluster)) return 0xffffffff; - return data_start + (cluster-2) * sectors_per_cluster + sector % sectors_per_cluster; + + /* Compute the sector within the partition and return it */ + return data_start + (uint32_t) (cluster-2) * sectors_per_cluster + offset; } -/* Load the boot block and find the first partition */ +/* + * ao_fat_setup_partition + * + * Load the boot block and find the first partition + */ static uint8_t ao_fat_setup_partition(void) { @@ -216,29 +270,40 @@ ao_fat_setup_partition(void) return 0; } - /* Just use the first partition */ - partition = &mbr[0x1be]; + /* Check to see if it's actually a boot block, in which + * case it's presumably not a paritioned device + */ + + if (mbr[0] == 0xeb) { + partition_start = 0; + partition_size = get_u16(mbr + 0x13); + if (partition_size == 0) + partition_size = get_u32(mbr + 0x20); + } else { + /* Just use the first partition */ + partition = &mbr[0x1be]; - partition_type = partition[4]; - switch (partition_type) { - case 4: /* FAT16 up to 32M */ - case 6: /* FAT16 over 32M */ - break; - case 0x0b: /* FAT32 up to 2047GB */ - case 0x0c: /* FAT32 LBA */ - break; - default: - printf ("Invalid partition type %02x\n", partition_type); - ao_bufio_put(mbr, 0); - return 0; - } + partition_type = partition[4]; + switch (partition_type) { + case 4: /* FAT16 up to 32M */ + case 6: /* FAT16 over 32M */ + break; + case 0x0b: /* FAT32 up to 2047GB */ + case 0x0c: /* FAT32 LBA */ + break; + default: + printf ("Invalid partition type %02x\n", partition_type); + ao_bufio_put(mbr, 0); + return 0; + } - partition_start = get_u32(partition+8); - partition_size = get_u32(partition+12); - if (partition_size == 0) { - printf ("Zero-sized partition\n"); - ao_bufio_put(mbr, 0); - return 0; + partition_start = get_u32(partition+8); + partition_size = get_u32(partition+12); + if (partition_size == 0) { + printf ("Zero-sized partition\n"); + ao_bufio_put(mbr, 0); + return 0; + } } partition_end = partition_start + partition_size; printf ("Partition type %02x start %08x end %08x\n", @@ -250,7 +315,8 @@ ao_fat_setup_partition(void) static uint8_t ao_fat_setup_fs(void) { - uint8_t *boot = ao_fat_block_get(0); + uint8_t *boot = ao_fat_sector_get(0); + uint32_t data_sectors; if (!boot) return 0; @@ -259,39 +325,45 @@ ao_fat_setup_fs(void) if (boot[0x1fe] != 0x55 || boot[0x1ff] != 0xaa) { printf ("Invalid BOOT signature %02x %02x\n", boot[0x1fe], boot[0x1ff]); - ao_bufio_put(boot, 0); + ao_fat_sector_put(boot, 0); return 0; } /* Check the sector size */ - if (get_u16(boot + 0xb) != 0x200) { + if (get_u16(boot + 0xb) != SECTOR_SIZE) { printf ("Invalid sector size %d\n", get_u16(boot + 0xb)); - ao_bufio_put(boot, 0); + ao_fat_sector_put(boot, 0); return 0; } sectors_per_cluster = boot[0xd]; - bytes_per_cluster = sectors_per_cluster << 9; + bytes_per_cluster = sectors_per_cluster << SECTOR_SHIFT; reserved_sector_count = get_u16(boot+0xe); number_fat = boot[0x10]; root_entries = get_u16(boot + 0x11); sectors_per_fat = get_u16(boot+0x16); + fat_start = reserved_sector_count;; + root_start = fat_start + number_fat * sectors_per_fat; + data_start = root_start + ((root_entries * DIRENT_SIZE + SECTOR_MASK) >> SECTOR_SHIFT); + + data_sectors = (partition_end - partition_start) - data_start; + + number_cluster = data_sectors / sectors_per_cluster; + printf ("sectors per cluster %d\n", sectors_per_cluster); printf ("reserved sectors %d\n", reserved_sector_count); printf ("number of FATs %d\n", number_fat); printf ("root entries %d\n", root_entries); printf ("sectors per fat %d\n", sectors_per_fat); - fat_start = reserved_sector_count;; - root_start = fat_start + number_fat * sectors_per_fat; - data_start = root_start + ((root_entries * 0x20 + 0x1ff) >> 9); - printf ("fat start %d\n", fat_start); printf ("root start %d\n", root_start); printf ("data start %d\n", data_start); + ao_fat_sector_put(boot, 0); + return 1; } @@ -300,49 +372,36 @@ ao_fat_setup(void) { if (!ao_fat_setup_partition()) return 0; + check_bufio("partition setup"); if (!ao_fat_setup_fs()) return 0; + check_bufio("fs setup"); return 1; } -/* - * Low-level directory operations - */ - /* * Basic file operations */ static struct ao_fat_dirent ao_file_dirent; static uint32_t ao_file_offset; +static uint8_t ao_file_opened; static uint32_t -ao_file_offset_to_sector(uint32_t offset) +ao_fat_offset_to_sector(uint32_t offset) { if (offset > ao_file_dirent.size) return 0xffffffff; - return ao_fat_sector_seek(ao_file_dirent.cluster, offset >> 9); -} - -uint8_t -ao_fat_open(char name[11]) -{ - uint16_t entry = 0; - struct ao_fat_dirent dirent; - - while (ao_fat_readdir(&entry, &dirent)) { - if (!memcmp(name, dirent.name, 11)) { - ao_file_dirent = dirent; - ao_file_offset = 0; - return 1; - } - } - return 0; + return ao_fat_sector_seek(ao_file_dirent.cluster, offset >> SECTOR_SHIFT); } - - -static uint8_t +/* + * ao_fat_set_size + * + * Set the size of the current file, truncating or extending + * the cluster chain as needed + */ +static int8_t ao_fat_set_size(uint32_t size) { uint16_t clear_cluster = 0; @@ -350,11 +409,9 @@ ao_fat_set_size(uint32_t size) uint16_t first_cluster; first_cluster = ao_file_dirent.cluster; - printf ("set size to %d\n", size); if (size == ao_file_dirent.size) - return 1; + return AO_FAT_SUCCESS; if (size == 0) { - printf ("erase file\n"); clear_cluster = ao_file_dirent.cluster; first_cluster = 0; } else { @@ -366,43 +423,50 @@ ao_fat_set_size(uint32_t size) if (new_num < old_num) { uint16_t last_cluster; - printf("Remove %d clusters\n", old_num - new_num); /* Go find the last cluster we want to preserve in the file */ last_cluster = ao_fat_cluster_seek(ao_file_dirent.cluster, new_num - 1); - printf ("Last cluster is now %04x\n", last_cluster); /* Rewrite that cluster entry with 0xffff to mark the end of the chain */ clear_cluster = ao_fat_entry_replace(last_cluster, 0xffff); } else if (new_num > old_num) { uint16_t need; uint16_t free; uint16_t last_cluster; + uint16_t highest_allocated = 0; if (old_num) last_cluster = ao_fat_cluster_seek(ao_file_dirent.cluster, old_num - 1); else last_cluster = 0; - need = new_num - old_num; - printf ("Need %d clusters\n", need); + if (first_free_cluster < 2 || number_cluster <= first_free_cluster) + first_free_cluster = 2; + /* See if there are enough free clusters in the file system */ - for (free = 2; need > 0 && (free - 2) < sectors_per_fat * 256; free++) { - if (!ao_fat_entry_read(free)) { - printf ("\tCluster %04x available\n", free); + need = new_num - old_num; + +#define loop_cluster for (free = first_free_cluster; need > 0;) +#define next_cluster \ + if (++free == number_cluster) \ + free = 2; \ + if (free == first_free_cluster) \ + break; \ + + loop_cluster { + if (!ao_fat_entry_read(free)) need--; - } + next_cluster; } /* Still need some, tell the user that we've failed */ - if (need) { - printf ("File system full\n"); - return 0; - } + if (need) + return -AO_FAT_ENOSPC; - need = new_num - old_num; /* Now go allocate those clusters */ - for (free = 2; need > 0 && (free - 2) < sectors_per_fat * 256; free++) { + need = new_num - old_num; + loop_cluster { if (!ao_fat_entry_read(free)) { - printf ("\tAllocate %04x\n", free); + if (free > highest_allocated) + highest_allocated = free; if (last_cluster) ao_fat_entry_replace(last_cluster, free); else @@ -410,153 +474,297 @@ ao_fat_set_size(uint32_t size) last_cluster = free; need--; } + next_cluster; } + first_free_cluster = highest_allocated + 1; + if (first_free_cluster >= number_cluster) + first_free_cluster = 2; + /* Mark the new end of the chain */ ao_fat_entry_replace(last_cluster, 0xffff); } } /* Deallocate clusters off the end of the file */ - if (ao_fat_cluster_valid(clear_cluster)) { - printf ("Clear clusters starting with %04x\n", clear_cluster); - ao_fat_clear_cluster_chain(clear_cluster); - } + if (ao_fat_cluster_valid(clear_cluster)) + ao_fat_free_cluster_chain(clear_cluster); + /* Update the directory entry */ dent = ao_fat_root_get(ao_file_dirent.entry); if (!dent) - return 0; + return -AO_FAT_EIO; put_u32(dent + 0x1c, size); put_u16(dent + 0x1a, first_cluster); ao_fat_root_put(dent, ao_file_dirent.entry, 1); ao_file_dirent.size = size; ao_file_dirent.cluster = first_cluster; - return 1; + return AO_FAT_SUCCESS; +} + +/* + * ao_fat_root_init + * + * Initialize a root directory entry + */ +void +ao_fat_root_init(uint8_t *dent, char name[11], uint8_t attr) +{ + memset(dent, '\0', 0x20); + memmove(dent, name, 11); + + dent[0x0b] = 0x00; + dent[0x0c] = 0x00; + dent[0x0d] = 0x00; + + /* XXX fix time */ + put_u16(dent + 0x0e, 0); + /* XXX fix date */ + put_u16(dent + 0x10, 0); + /* XXX fix date */ + put_u16(dent + 0x12, 0); + + /* XXX fix time */ + put_u16(dent + 0x16, 0); + /* XXX fix date */ + put_u16(dent + 0x18, 0); + + /* cluster number */ + /* Low cluster bytes */ + put_u16(dent + 0x1a, 0); + /* FAT32 high cluster bytes */ + put_u16(dent + 0x14, 0); + + /* size */ + put_u32(dent + 0x1c, 0); +} + + +static void +ao_fat_dirent_init(uint8_t *dent, uint16_t entry, struct ao_fat_dirent *dirent) +{ + memcpy(dirent->name, dent + 0x00, 11); + dirent->attr = dent[0x0b]; + dirent->size = get_u32(dent+0x1c); + dirent->cluster = get_u16(dent+0x1a); + dirent->entry = entry; +} + +/* + * Public API + */ + +/* + * ao_fat_open + * + * Open an existing file. + */ +int8_t +ao_fat_open(char name[11], uint8_t mode) +{ + uint16_t entry = 0; + struct ao_fat_dirent dirent; + + if (ao_file_opened) + return -AO_FAT_EMFILE; + + while (ao_fat_readdir(&entry, &dirent)) { + if (!memcmp(name, dirent.name, 11)) { + if (AO_FAT_IS_DIR(dirent.attr)) + return -AO_FAT_EISDIR; + if (!AO_FAT_IS_FILE(dirent.attr)) + return -AO_FAT_EPERM; + if (mode > AO_FAT_OPEN_READ && (dirent.attr & AO_FAT_FILE_READ_ONLY)) + return -AO_FAT_EACCESS; + ao_file_dirent = dirent; + ao_file_offset = 0; + ao_file_opened = 1; + return AO_FAT_SUCCESS; + } + } + return -AO_FAT_ENOENT; } -uint8_t +/* + * ao_fat_creat + * + * Open and truncate an existing file or + * create a new file + */ +int8_t ao_fat_creat(char name[11]) { uint16_t entry; + int8_t status; + + if (ao_file_opened) + return -AO_FAT_EMFILE; + + status = ao_fat_open(name, AO_FAT_OPEN_WRITE); - if (ao_fat_open(name)) - return ao_fat_set_size(0); - - for (entry = 0; entry < root_entries; entry++) { - uint8_t *dent = ao_fat_root_get(entry); - - if (dent[0] == AO_FAT_DENT_EMPTY || - dent[0] == AO_FAT_DENT_END) { - memmove(dent, name, 11); - dent[0x0b] = 0x00; - dent[0x0c] = 0x00; - dent[0x0d] = 0x00; - /* XXX fix time */ - put_u16(dent + 0x0e, 0); - /* XXX fix date */ - put_u16(dent + 0x10, 0); - /* XXX fix date */ - put_u16(dent + 0x12, 0); - /* XXX FAT32 high cluster bytes */ - put_u16(dent + 0x14, 0); - /* XXX fix time */ - put_u16(dent + 0x16, 0); - /* XXX fix date */ - put_u16(dent + 0x18, 0); - /* cluster number */ - put_u16(dent + 0x1a, 0); - /* size */ - put_u32(dent + 0x1c, 0); - ao_fat_root_put(dent, entry, 1); - return ao_fat_open(name); + switch (status) { + case -AO_FAT_SUCCESS: + status = ao_fat_set_size(0); + break; + case -AO_FAT_ENOENT: + for (entry = 0; entry < root_entries; entry++) { + uint8_t *dent = ao_fat_root_get(entry); + + if (!dent) { + status = -AO_FAT_EIO; + ao_fat_root_put(dent, entry, 0); + break; + } + + if (dent[0] == AO_FAT_DENT_EMPTY || dent[0] == AO_FAT_DENT_END) { + ao_fat_root_init(dent, name, AO_FAT_FILE_REGULAR); + ao_fat_dirent_init(dent, entry, &ao_file_dirent); + ao_fat_root_put(dent, entry, 1); + ao_file_opened = 1; + status = -AO_FAT_SUCCESS; + break; + } else { + ao_fat_root_put(dent, entry, 0); + } } + if (entry == root_entries) + status = -AO_FAT_ENOSPC; } - return 0; + return status; } -void +/* + * ao_fat_close + * + * Close the currently open file + */ +int8_t ao_fat_close(void) { + if (!ao_file_opened) + return -AO_FAT_EBADF; + memset(&ao_file_dirent, '\0', sizeof (struct ao_fat_dirent)); + ao_file_offset = 0; + ao_file_opened = 0; ao_bufio_flush(); + return AO_FAT_SUCCESS; } +/* + * ao_fat_read + * + * Read from the file + */ int -ao_fat_read(uint8_t *dest, int len) +ao_fat_read(void *dst, int len) { + uint8_t *dst_b = dst; uint32_t sector; uint16_t this_time; uint16_t offset; uint8_t *buf; int ret = 0; + if (!ao_file_opened) + return -AO_FAT_EBADF; + if (ao_file_offset + len > ao_file_dirent.size) len = ao_file_dirent.size - ao_file_offset; + if (len < 0) + len = 0; + while (len) { - offset = ao_file_offset & 0x1ff; - if (offset + len < 512) + offset = ao_file_offset & SECTOR_MASK; + if (offset + len < SECTOR_SIZE) this_time = len; else - this_time = 512 - offset; + this_time = SECTOR_SIZE - offset; - sector = ao_file_offset_to_sector(ao_file_offset); + sector = ao_fat_offset_to_sector(ao_file_offset); if (sector == 0xffffffff) break; - buf = ao_fat_block_get(sector); - if (!buf) + buf = ao_fat_sector_get(sector); + if (!buf) { + ret = -AO_FAT_EIO; break; - memcpy(dest, buf + offset, this_time); - ao_fat_block_put(buf, 0); + } + memcpy(dst_b, buf + offset, this_time); + ao_fat_sector_put(buf, 0); ret += this_time; len -= this_time; - dest += this_time; + dst_b += this_time; ao_file_offset += this_time; } return ret; } +/* + * ao_fat_write + * + * Write to the file, extended as necessary + */ int -ao_fat_write(uint8_t *src, int len) +ao_fat_write(void *src, int len) { + uint8_t *src_b = src; uint32_t sector; uint16_t this_time; uint16_t offset; uint8_t *buf; int ret = 0; + if (!ao_file_opened) + return -AO_FAT_EBADF; + if (ao_file_offset + len > ao_file_dirent.size) { - if (!ao_fat_set_size(ao_file_offset + len)) - return 0; + ret = ao_fat_set_size(ao_file_offset + len); + if (ret < 0) + return ret; } while (len) { - offset = ao_file_offset & 0x1ff; - if (offset + len < 512) + offset = ao_file_offset & SECTOR_MASK; + if (offset + len < SECTOR_SIZE) this_time = len; else - this_time = 512 - offset; + this_time = SECTOR_SIZE - offset; - sector = ao_file_offset_to_sector(ao_file_offset); + sector = ao_fat_offset_to_sector(ao_file_offset); if (sector == 0xffffffff) break; - buf = ao_fat_block_get(sector); - if (!buf) + buf = ao_fat_sector_get(sector); + if (!buf) { + ret = -AO_FAT_EIO; break; - memcpy(buf + offset, src, this_time); - ao_fat_block_put(buf, 1); + } + memcpy(buf + offset, src_b, this_time); + ao_fat_sector_put(buf, 1); ret += this_time; len -= this_time; - src += this_time; + src_b += this_time; ao_file_offset += this_time; } - return 0; + return ret; } -uint32_t +/* + * ao_fat_seek + * + * Set the position for the next I/O operation + * Note that this doesn't actually change the size + * of the file if the requested position is beyond + * the current file length, that would take a future + * write + */ +int32_t ao_fat_seek(int32_t pos, uint8_t whence) { + if (!ao_file_opened) + return -AO_FAT_EBADF; + switch (whence) { case AO_FAT_SEEK_SET: ao_file_offset = pos; @@ -568,12 +776,16 @@ ao_fat_seek(int32_t pos, uint8_t whence) ao_file_offset = ao_file_dirent.size + pos; break; } - if (ao_file_offset > ao_file_dirent.size) - ao_fat_set_size(ao_file_offset); return ao_file_offset; } -uint8_t +/* + * ao_fat_unlink + * + * Remove a file from the directory, marking + * all clusters as free + */ +int8_t ao_fat_unlink(char name[11]) { uint16_t entry = 0; @@ -584,7 +796,13 @@ ao_fat_unlink(char name[11]) uint8_t *next; uint8_t *ent; uint8_t delete; - ao_fat_clear_cluster_chain(dirent.cluster); + + if (AO_FAT_IS_DIR(dirent.attr)) + return -AO_FAT_EISDIR; + if (!AO_FAT_IS_FILE(dirent.attr)) + return -AO_FAT_EPERM; + + ao_fat_free_cluster_chain(dirent.cluster); next = ao_fat_root_get(dirent.entry + 1); if (next && next[0] != AO_FAT_DENT_END) delete = AO_FAT_DENT_EMPTY; @@ -594,24 +812,24 @@ ao_fat_unlink(char name[11]) ao_fat_root_put(next, dirent.entry + 1, 0); ent = ao_fat_root_get(dirent.entry); if (ent) { - memset(ent, '\0', 0x20); + memset(ent, '\0', DIRENT_SIZE); *ent = delete; ao_fat_root_put(ent, dirent.entry, 1); } ao_bufio_flush(); - return 1; + return AO_FAT_SUCCESS; } } - return 0; + return -AO_FAT_ENOENT; } -uint8_t +int8_t ao_fat_rename(char old[11], char new[11]) { - return 0; + return -AO_FAT_EIO; } -uint8_t +int8_t ao_fat_readdir(uint16_t *entry, struct ao_fat_dirent *dirent) { uint8_t *dent; @@ -625,20 +843,15 @@ ao_fat_readdir(uint16_t *entry, struct ao_fat_dirent *dirent) ao_fat_root_put(dent, *entry, 0); return 0; } - if (dent[0] != AO_FAT_DENT_EMPTY && - (dent[0x0b] & (AO_FAT_FILE_DIRECTORY|AO_FAT_FILE_VOLUME_LABEL)) == 0) - break; + if (dent[0] != AO_FAT_DENT_EMPTY && (dent[0xb] & 0xf) != 0xf) { + ao_fat_dirent_init(dent, *entry, dirent); + ao_fat_root_put(dent, *entry, 0); + (*entry)++; + return 1; + } ao_fat_root_put(dent, *entry, 0); (*entry)++; } - memcpy(dirent->name, dent, 11); - dirent->attr = dent[0xb]; - dirent->size = get_u32(dent+0x1c); - dirent->cluster = get_u16(dent+0x1a); - dirent->entry = *entry; - ao_fat_root_put(dent, *entry, 0); - (*entry)++; - return 1; } static void @@ -648,8 +861,12 @@ ao_fat_list(void) struct ao_fat_dirent dirent; while (ao_fat_readdir(&entry, &dirent)) { - printf ("%-8.8s.%-3.3s %02x %d\n", - dirent.name, dirent.name + 8, dirent.attr, dirent.size); + printf ("%-8.8s.%-3.3s %02x %04x %d\n", + dirent.name, + dirent.name + 8, + dirent.attr, + dirent.cluster, + dirent.size); } } @@ -671,4 +888,3 @@ ao_fat_init(void) ao_bufio_init(); ao_cmd_register(&ao_fat_cmds[0]); } - diff --git a/src/drivers/ao_fat.h b/src/drivers/ao_fat.h index 2bf6222e..5b9b300f 100644 --- a/src/drivers/ao_fat.h +++ b/src/drivers/ao_fat.h @@ -21,6 +21,7 @@ void ao_fat_init(void); +#define AO_FAT_FILE_REGULAR 0x00 #define AO_FAT_FILE_READ_ONLY 0x01 #define AO_FAT_FILE_HIDDEN 0x02 #define AO_FAT_FILE_SYSTEM 0x04 @@ -31,32 +32,52 @@ ao_fat_init(void); #define AO_FAT_DENT_EMPTY 0xe5 #define AO_FAT_DENT_END 0x00 -uint8_t -ao_fat_open(char name[11]); - -uint8_t +#define AO_FAT_IS_FILE(attr) (((attr) & (AO_FAT_FILE_VOLUME_LABEL|AO_FAT_FILE_DIRECTORY|AO_FAT_FILE_ARCHIVE)) == 0) +#define AO_FAT_IS_DIR(attr) (((attr) & (AO_FAT_FILE_DIRECTORY)) == AO_FAT_FILE_DIRECTORY) + +#define AO_FAT_SUCCESS 0 +#define AO_FAT_EPERM 1 +#define AO_FAT_ENOENT 2 +#define AO_FAT_EIO 4 +#define AO_FAT_EBADF 9 +#define AO_FAT_EACCESS 13 +#define AO_FAT_EEXIST 17 +#define AO_FAT_ENOTDIR 20 +#define AO_FAT_EISDIR 21 +#define AO_FAT_EMFILE 24 +#define AO_FAT_EFBIG 27 +#define AO_FAT_ENOSPC 28 + +int8_t +ao_fat_open(char name[11], uint8_t mode); + +#define AO_FAT_OPEN_READ 0 +#define AO_FAT_OPEN_WRITE 1 +#define AO_FAT_OPEN_RW 2 + +int8_t ao_fat_creat(char name[11]); -void +int8_t ao_fat_close(void); int -ao_fat_read(uint8_t *dest, int len); +ao_fat_read(void *dest, int len); int -ao_fat_write(uint8_t *buf, int len); +ao_fat_write(void *src, int len); #define AO_FAT_SEEK_SET 0 #define AO_FAT_SEEK_CUR 1 #define AO_FAT_SEEK_END 2 -uint32_t -bao_fat_seek(int32_t pos, uint8_t whence); +int32_t +ao_fat_seek(int32_t pos, uint8_t whence); -uint8_t +int8_t ao_fat_unlink(char name[11]); -uint8_t +int8_t ao_fat_rename(char old[11], char new[11]); struct ao_fat_dirent { @@ -67,7 +88,7 @@ struct ao_fat_dirent { uint16_t entry; }; -uint8_t +int8_t ao_fat_readdir(uint16_t *entry, struct ao_fat_dirent *dirent); #endif /* _AO_FAT_H_ */ diff --git a/src/test/Makefile b/src/test/Makefile index 96170cc1..991bdbfc 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -66,4 +66,4 @@ ao_micropeak_test: ao_micropeak_test.c ao_microflight.c ao_kalman.h cc $(CFLAGS) -o $@ ao_micropeak_test.c -lm ao_fat_test: ao_fat_test.c ao_fat.c ao_bufio.c - cc $(CFLAGS) -o $@ ao_fat_test.c + cc $(CFLAGS) -o $@ ao_fat_test.c -lssl diff --git a/src/test/ao_fat_test.c b/src/test/ao_fat_test.c index 22ac03ad..3f947034 100644 --- a/src/test/ao_fat_test.c +++ b/src/test/ao_fat_test.c @@ -18,11 +18,13 @@ #include #include #include +#include #include #include #include #include #include +#include #define AO_FAT_TEST @@ -40,7 +42,7 @@ void ao_panic(uint8_t panic) { printf ("panic %d\n", panic); - exit(1); + abort(); } #define AO_PANIC_BUFIO 15 @@ -64,9 +66,12 @@ struct ao_cmds { int fs_fd; +uint64_t total_reads, total_writes; + uint8_t ao_sdcard_read_block(uint32_t block, uint8_t *data) { + ++total_reads; lseek(fs_fd, block * 512, 0); return read(fs_fd, data, 512) == 512; } @@ -74,45 +79,308 @@ ao_sdcard_read_block(uint32_t block, uint8_t *data) uint8_t ao_sdcard_write_block(uint32_t block, uint8_t *data) { + ++total_writes; lseek(fs_fd, block * 512, 0); return write(fs_fd, data, 512) == 512; } +char *fs = "fs.fat"; + void ao_sdcard_init(void) { - fs_fd = open("fat.fs", 2); + char cmd[1024]; + + snprintf(cmd, sizeof(cmd), "rm -f %s && mkfs.vfat -C %s 16384", fs, fs); + if (system (cmd) != 0) { + fprintf(stderr, "'%s' failed\n", cmd); + exit(1); + } + fs_fd = open(fs, 2); + if (fs_fd < 0) { + perror (fs); + exit(1); + } } #include "ao_bufio.c" +void +check_bufio(char *where) +{ + int b; + + for (b = 0; b < AO_NUM_BUF; b++) { + if (ao_bufio[b].busy) { + printf ("%s: buffer %d busy. block %d seqno %u\n", + where, b, ao_bufio[b].block, ao_bufio[b].seqno & 0xffff); + abort(); + } + } +} + + +void +check_fat(void); + #include "ao_fat.c" +/* Get the next cluster entry in the chain */ +static uint16_t +ao_fat_entry_raw_read(uint16_t cluster, uint8_t fat) +{ + uint32_t sector; + uint16_t offset; + uint8_t *buf; + uint16_t ret; + +// cluster -= 2; + sector = cluster >> (SECTOR_SHIFT - 1); + offset = (cluster << 1) & SECTOR_MASK; + buf = ao_fat_sector_get(fat_start + fat * sectors_per_fat + sector); + if (!buf) + return 0; + ret = get_u16(buf + offset); + ao_fat_sector_put(buf, 0); + return ret; +} + +void +dump_fat(void) +{ + int e; + + printf ("\n **** FAT ****\n\n"); + for (e = 0; e < number_cluster; e++) { + if ((e & 0xf) == 0x0) + printf ("%04x: ", e); + printf (" %04x", ao_fat_entry_raw_read(e, 0)); + if ((e & 0xf) == 0xf) + putchar ('\n'); + } +} + +void +fat_list(void) +{ + uint16_t entry = 0; + struct ao_fat_dirent dirent; + + printf (" **** Root directory ****\n"); + while (ao_fat_readdir(&entry, &dirent)) { + printf ("%04x: %-8.8s.%-3.3s %02x %04x %d\n", + entry, + dirent.name, + dirent.name + 8, + dirent.attr, + dirent.cluster, + dirent.size); + } + + printf (" **** End of root directory ****\n"); +} + +void +fatal(char *msg, ...) +{ + dump_fat(); + fat_list(); + + va_list l; + va_start(l, msg); + vfprintf(stderr, msg, l); + va_end(l); + + abort(); +} + +void +check_fat(void) +{ + int e; + int f; + + for (e = 0; e < number_cluster; e++) { + uint16_t v = ao_fat_entry_raw_read(e, 0); + for (f = 1; f < number_fat; f++) { + if (ao_fat_entry_raw_read(e, f) != v) + fatal ("fats differ at %d\n", e); + } + } +} + +uint16_t +check_file(uint16_t dent, uint16_t first_cluster, uint8_t *used) +{ + uint16_t clusters = 0; + uint16_t cluster; + + if (!first_cluster) + return 0; + + for (cluster = first_cluster; + (cluster & 0xfff8) != 0xfff8; + cluster = ao_fat_entry_raw_read(cluster, 0)) + { + if (!ao_fat_cluster_valid(cluster)) + fatal("file %d: invalid cluster %04x\n", dent, cluster); + if (used[cluster]) + fatal("file %d: duplicate cluster %04x\n", dent, cluster); + used[cluster] = 1; + clusters++; + } + return clusters; +} + +void +check_fs(void) +{ + uint16_t r; + uint16_t cluster, chain; + uint8_t *used; + + check_fat(); + + used = calloc(1, number_cluster); + + for (r = 0; r < root_entries; r++) { + uint8_t *dent = ao_fat_root_get(r); + uint16_t clusters; + uint32_t size; + uint16_t first_cluster; + uint8_t name[11]; + + if (!dent) + fatal("cannot map dent %d\n", r); + memcpy(name, dent+0, 11); + first_cluster = get_u16(dent + 0x1a); + size = get_u32(dent + 0x1c); + ao_fat_root_put(dent, r, 0); + + if (name[0] == AO_FAT_DENT_END) { + break; + } + + clusters = check_file(r, first_cluster, used); + if (size > clusters * bytes_per_cluster) + fatal("file %d: size %u beyond clusters %d (%u)\n", + r, size, clusters, clusters * bytes_per_cluster); + if (size <= (clusters - 1) * bytes_per_cluster) + fatal("file %d: size %u too small clusters %d (%u)\n", + r, size, clusters, clusters * bytes_per_cluster); + } + for (; r < root_entries; r++) { + uint8_t *dent = ao_fat_root_get(r); + if (!dent) + fatal("cannot map dent %d\n", r); + if (dent[0] != AO_FAT_DENT_END) + fatal("found non-zero dent past end %d\n", r); + ao_fat_root_put(dent, r, 0); + } + + for (cluster = 0; cluster < 2; cluster++) { + chain = ao_fat_entry_raw_read(cluster, 0); + + if ((chain & 0xfff8) != 0xfff8) + fatal("cluster %d: not marked busy\n", cluster); + } + for (; cluster < number_cluster; cluster++) { + chain = ao_fat_entry_raw_read(cluster, 0); + + if (chain != 0) { + if (used[cluster] == 0) + fatal("cluster %d: marked busy, but not in any file\n", cluster); + } else { + if (used[cluster] != 0) + fatal("cluster %d: marked free, but foudn in file\n", cluster); + } + } +} + +#define NUM_FILES 512 +#define LINES_FILE 1000 + +uint32_t sizes[NUM_FILES]; + +unsigned char md5[NUM_FILES][MD5_DIGEST_LENGTH]; + int main(int argc, char **argv) { - uint8_t data[15]; - int len; + char name[12]; + int id; + MD5_CTX ctx; + unsigned char md5_check[MD5_DIGEST_LENGTH]; + + if (argv[1]) + fs = argv[1]; + ao_fat_init(); - ao_fat_test(); - if (ao_fat_open("DATALOG TXT")) { - printf ("DATALOG.TXT\n"); - while ((len = ao_fat_read(data, sizeof (data))) > 0) { - write(1, data, len); + + check_bufio("top"); + ao_fat_setup(); + + check_fs(); + check_bufio("after setup"); + printf (" **** Creating %d files\n", NUM_FILES); + + for (id = 0; id < NUM_FILES; id++) { + sprintf(name, "D%07dTXT", id); + if (ao_fat_creat(name) == AO_FAT_SUCCESS) { + int j; + char line[64]; + check_bufio("file created"); + MD5_Init(&ctx); + for (j = 0; j < 1000; j++) { + int len; + sprintf (line, "Hello, world %d %d\r\n", id, j); + len = strlen(line); + ao_fat_write((uint8_t *) line, len); + MD5_Update(&ctx, line, len); + sizes[id] += len; + } + ao_fat_close(); + MD5_Final(&md5[id][0], &ctx); + if (id == 0) { + printf ("MD5 write %d:", id); + for (j = 0; j < MD5_DIGEST_LENGTH; j++) + printf(" %02x", md5[id][j]); + printf ("\n"); + } + check_bufio("file written"); } - ao_fat_close(); -// ao_fat_unlink("DATALOG TXT"); } - if (ao_fat_open("NEWFILE TXT")) { - printf ("NEWFILE.TXT\n"); - while ((len = ao_fat_read(data, sizeof (data))) > 0) { - write(1, data, len); + + check_bufio("all files created"); + printf (" **** All done creating files\n"); + check_fs(); + + printf (" **** Comparing %d files\n", NUM_FILES); + + for (id = 0; id < NUM_FILES; id++) { + char buf[337]; + sprintf(name, "D%07dTXT", id); + if (ao_fat_open(name, AO_FAT_OPEN_READ) == AO_FAT_SUCCESS) { + int len; + + MD5_Init(&ctx); + while ((len = ao_fat_read((uint8_t *) buf, sizeof(buf))) > 0) { + MD5_Update(&ctx, buf, len); + } + ao_fat_close(); + MD5_Final(md5_check, &ctx); + if (id == 0) { + int j; + printf ("MD5 read %d:", id); + for (j = 0; j < MD5_DIGEST_LENGTH; j++) + printf(" %02x", md5_check[j]); + printf ("\n"); + } + if (memcmp(md5_check, &md5[id][0], sizeof (md5_check)) != 0) + fatal ("checksum failed file %d\n", id); + check_bufio("file shown"); } - ao_fat_close(); - } - if (ao_fat_creat ("NEWFILE TXT")) { - for (len = 0; len < 4095; len++) - ao_fat_write((uint8_t *) "hello, world!\n", 14); - ao_fat_close(); } + + printf ("\n **** Total IO: read %llu write %llu\n", total_reads, total_writes); return 0; } -- cgit v1.2.3 From 8101e4af199a3d79bff434f788cce9f97aeac53a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Mar 2013 16:57:02 -0700 Subject: altos: Add a simple cache for the FAT position->cluster computation This improves read/write performance with large files by not re-walking the cluster chain for every operation Signed-off-by: Keith Packard --- src/drivers/ao_fat.c | 101 ++++++++++++++++++++++++++++--------------------- src/test/ao_fat_test.c | 58 ++++++++++++++-------------- 2 files changed, 88 insertions(+), 71 deletions(-) (limited to 'src/test') diff --git a/src/drivers/ao_fat.c b/src/drivers/ao_fat.c index c0412380..65c5ea7c 100644 --- a/src/drivers/ao_fat.c +++ b/src/drivers/ao_fat.c @@ -136,7 +136,6 @@ ao_fat_entry_read(uint16_t cluster) if (!ao_fat_cluster_valid(cluster)) return 0xfff7; -// cluster -= 2; sector = cluster >> (SECTOR_SHIFT - 1); offset = (cluster << 1) & SECTOR_MASK; buf = ao_fat_sector_get(fat_start + sector); @@ -162,7 +161,6 @@ ao_fat_entry_replace(uint16_t cluster, uint16_t new_value) if (!ao_fat_cluster_valid(cluster)) return 0; -// cluster -= 2; sector = cluster >> (SECTOR_SHIFT - 1); offset = (cluster << 1) & SECTOR_MASK; buf = ao_fat_sector_get(fat_start + sector); @@ -203,8 +201,11 @@ ao_fat_free_cluster_chain(uint16_t cluster) /* * ao_fat_cluster_seek * - * Walk a cluster chain the specified distance and return what we find - * there. If distance is zero, return the provided cluster. + * The basic file system operation -- map a file cluster index to a + * partition cluster number. Done by computing the cluster number and + * then walking that many clusters from the first cluster. Returns + * 0xffff if we walk off the end of the file or the cluster chain + * is damaged somehow */ static uint16_t ao_fat_cluster_seek(uint16_t cluster, uint16_t distance) @@ -218,34 +219,6 @@ ao_fat_cluster_seek(uint16_t cluster, uint16_t distance) return cluster; } -/* - * ao_fat_sector_seek - * - * The basic file system operation -- map a file sector number to a - * partition sector number. Done by computing the cluster number and - * then walking that many clusters from the first cluster, then - * adding the sector offset from the start of the cluster. Returns - * 0xffffffff if we walk off the end of the file or the cluster chain - * is damaged somehow - */ -static uint32_t -ao_fat_sector_seek(uint16_t cluster, uint32_t sector) -{ - uint16_t distance; - uint16_t offset; - - distance = sector / sectors_per_cluster; - offset = sector % sectors_per_cluster; - - cluster = ao_fat_cluster_seek(cluster, distance); - - if (!ao_fat_cluster_valid(cluster)) - return 0xffffffff; - - /* Compute the sector within the partition and return it */ - return data_start + (uint32_t) (cluster-2) * sectors_per_cluster + offset; -} - /* * ao_fat_setup_partition * @@ -385,14 +358,51 @@ ao_fat_setup(void) static struct ao_fat_dirent ao_file_dirent; static uint32_t ao_file_offset; +static uint32_t ao_file_cluster_offset; +static uint16_t ao_file_cluster; static uint8_t ao_file_opened; static uint32_t -ao_fat_offset_to_sector(uint32_t offset) +ao_fat_current_sector(void) { - if (offset > ao_file_dirent.size) + uint16_t cluster_offset; + uint32_t sector_offset; + uint16_t sector_index; + uint16_t cluster; + + if (ao_file_offset > ao_file_dirent.size) return 0xffffffff; - return ao_fat_sector_seek(ao_file_dirent.cluster, offset >> SECTOR_SHIFT); + + sector_offset = ao_file_offset >> SECTOR_SHIFT; + + if (!ao_file_cluster) { + cluster_offset = sector_offset / sectors_per_cluster; + + cluster = ao_fat_cluster_seek(ao_file_dirent.cluster, cluster_offset); + if (!ao_fat_cluster_valid(cluster)) + return 0xffffffff; + ao_file_cluster = cluster; + ao_file_cluster_offset = cluster_offset * bytes_per_cluster; + } + + sector_index = sector_offset % sectors_per_cluster; + return data_start + (uint32_t) (ao_file_cluster-2) * sectors_per_cluster + sector_index; +} + +static void +ao_fat_set_offset(uint32_t offset) +{ + + if (offset == 0) { + ao_file_cluster = ao_file_dirent.cluster; + ao_file_cluster_offset = 0; + } + else if (offset < ao_file_cluster_offset || + ao_file_cluster_offset + bytes_per_cluster <= offset) + { + ao_file_cluster = 0; + } + ao_file_offset = offset; } /* @@ -576,7 +586,7 @@ ao_fat_open(char name[11], uint8_t mode) if (mode > AO_FAT_OPEN_READ && (dirent.attr & AO_FAT_FILE_READ_ONLY)) return -AO_FAT_EACCESS; ao_file_dirent = dirent; - ao_file_offset = 0; + ao_fat_set_offset(0); ao_file_opened = 1; return AO_FAT_SUCCESS; } @@ -620,6 +630,7 @@ ao_fat_creat(char name[11]) ao_fat_dirent_init(dent, entry, &ao_file_dirent); ao_fat_root_put(dent, entry, 1); ao_file_opened = 1; + ao_fat_set_offset(0); status = -AO_FAT_SUCCESS; break; } else { @@ -645,6 +656,7 @@ ao_fat_close(void) memset(&ao_file_dirent, '\0', sizeof (struct ao_fat_dirent)); ao_file_offset = 0; + ao_file_cluster = 0; ao_file_opened = 0; ao_bufio_flush(); return AO_FAT_SUCCESS; @@ -681,7 +693,7 @@ ao_fat_read(void *dst, int len) else this_time = SECTOR_SIZE - offset; - sector = ao_fat_offset_to_sector(ao_file_offset); + sector = ao_fat_current_sector(); if (sector == 0xffffffff) break; buf = ao_fat_sector_get(sector); @@ -695,7 +707,7 @@ ao_fat_read(void *dst, int len) ret += this_time; len -= this_time; dst_b += this_time; - ao_file_offset += this_time; + ao_fat_set_offset(ao_file_offset + this_time); } return ret; } @@ -731,7 +743,7 @@ ao_fat_write(void *src, int len) else this_time = SECTOR_SIZE - offset; - sector = ao_fat_offset_to_sector(ao_file_offset); + sector = ao_fat_current_sector(); if (sector == 0xffffffff) break; buf = ao_fat_sector_get(sector); @@ -745,7 +757,7 @@ ao_fat_write(void *src, int len) ret += this_time; len -= this_time; src_b += this_time; - ao_file_offset += this_time; + ao_fat_set_offset(ao_file_offset + this_time); } return ret; } @@ -762,20 +774,23 @@ ao_fat_write(void *src, int len) int32_t ao_fat_seek(int32_t pos, uint8_t whence) { + uint32_t new_offset = ao_file_offset; + if (!ao_file_opened) return -AO_FAT_EBADF; switch (whence) { case AO_FAT_SEEK_SET: - ao_file_offset = pos; + new_offset = pos; break; case AO_FAT_SEEK_CUR: - ao_file_offset += pos; + new_offset += pos; break; case AO_FAT_SEEK_END: - ao_file_offset = ao_file_dirent.size + pos; + new_offset = ao_file_dirent.size + pos; break; } + ao_fat_set_offset(new_offset); return ao_file_offset; } diff --git a/src/test/ao_fat_test.c b/src/test/ao_fat_test.c index 3f947034..fffd5af4 100644 --- a/src/test/ao_fat_test.c +++ b/src/test/ao_fat_test.c @@ -261,12 +261,17 @@ check_fs(void) } clusters = check_file(r, first_cluster, used); - if (size > clusters * bytes_per_cluster) - fatal("file %d: size %u beyond clusters %d (%u)\n", - r, size, clusters, clusters * bytes_per_cluster); - if (size <= (clusters - 1) * bytes_per_cluster) - fatal("file %d: size %u too small clusters %d (%u)\n", - r, size, clusters, clusters * bytes_per_cluster); + if (size == 0) { + if (clusters != 0) + fatal("file %d: zero sized, but %d clusters\n", clusters); + } else { + if (size > clusters * bytes_per_cluster) + fatal("file %d: size %u beyond clusters %d (%u)\n", + r, size, clusters, clusters * bytes_per_cluster); + if (size <= (clusters - 1) * bytes_per_cluster) + fatal("file %d: size %u too small clusters %d (%u)\n", + r, size, clusters, clusters * bytes_per_cluster); + } } for (; r < root_entries; r++) { uint8_t *dent = ao_fat_root_get(r); @@ -296,8 +301,8 @@ check_fs(void) } } -#define NUM_FILES 512 -#define LINES_FILE 1000 +#define NUM_FILES 10 +#define LINES_FILE 80000 uint32_t sizes[NUM_FILES]; @@ -330,22 +335,20 @@ main(int argc, char **argv) char line[64]; check_bufio("file created"); MD5_Init(&ctx); - for (j = 0; j < 1000; j++) { - int len; + for (j = 0; j < LINES_FILE; j++) { + int len, ret; sprintf (line, "Hello, world %d %d\r\n", id, j); len = strlen(line); - ao_fat_write((uint8_t *) line, len); - MD5_Update(&ctx, line, len); - sizes[id] += len; + ret = ao_fat_write((uint8_t *) line, len); + if (ret <= 0) + break; + MD5_Update(&ctx, line, ret); + sizes[id] += ret; + if (ret != len) + printf ("write failed %d\n", ret); } ao_fat_close(); MD5_Final(&md5[id][0], &ctx); - if (id == 0) { - printf ("MD5 write %d:", id); - for (j = 0; j < MD5_DIGEST_LENGTH; j++) - printf(" %02x", md5[id][j]); - printf ("\n"); - } check_bufio("file written"); } } @@ -357,26 +360,25 @@ main(int argc, char **argv) printf (" **** Comparing %d files\n", NUM_FILES); for (id = 0; id < NUM_FILES; id++) { - char buf[337]; + char buf[337]; + uint32_t size; sprintf(name, "D%07dTXT", id); + size = 0; if (ao_fat_open(name, AO_FAT_OPEN_READ) == AO_FAT_SUCCESS) { int len; MD5_Init(&ctx); while ((len = ao_fat_read((uint8_t *) buf, sizeof(buf))) > 0) { MD5_Update(&ctx, buf, len); + size += len; } ao_fat_close(); MD5_Final(md5_check, &ctx); - if (id == 0) { - int j; - printf ("MD5 read %d:", id); - for (j = 0; j < MD5_DIGEST_LENGTH; j++) - printf(" %02x", md5_check[j]); - printf ("\n"); - } + if (size != sizes[id]) + fatal("file %d: size differs %d written %d read\n", + id, sizes[id], size); if (memcmp(md5_check, &md5[id][0], sizeof (md5_check)) != 0) - fatal ("checksum failed file %d\n", id); + fatal ("file %d: checksum failed\n", id); check_bufio("file shown"); } } -- cgit v1.2.3 From 86e1039e14304ac13db540f2ee3afd4ff170b8b4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 29 Mar 2013 00:32:23 -0700 Subject: altos: Add FAT32 support. And lots more testing. Generalizes the FAT code to deal with either 16-bit or 32-bit versions. The testing code now runs over a variety of disk images to check for compatibility on all of them. Signed-off-by: Keith Packard --- src/drivers/ao_bufio.c | 16 +- src/drivers/ao_bufio.h | 3 + src/drivers/ao_fat.c | 569 ++++++++++++++++++++++++++++++++++--------------- src/drivers/ao_fat.h | 39 +++- src/test/ao_fat_test.c | 236 ++++++++++++++------ 5 files changed, 612 insertions(+), 251 deletions(-) (limited to 'src/test') diff --git a/src/drivers/ao_bufio.c b/src/drivers/ao_bufio.c index 10b32ceb..87de457f 100644 --- a/src/drivers/ao_bufio.c +++ b/src/drivers/ao_bufio.c @@ -22,7 +22,7 @@ #include "ao_sdcard.h" #include "ao_bufio.h" -#define AO_NUM_BUF 4 +#define AO_NUM_BUF 16 #define AO_BUFSIZ 512 struct ao_bufio { @@ -292,13 +292,21 @@ static const struct ao_cmds ao_bufio_cmds[] = { }; void -ao_bufio_init(void) +ao_bufio_setup(void) { int b; - for (b = 0; b < AO_NUM_BUF; b++) + for (b = 0; b < AO_NUM_BUF; b++) { + ao_bufio[b].dirty = 0; + ao_bufio[b].busy = 0; ao_bufio[b].block = 0xffffffff; - ao_sdcard_init(); + } +} +void +ao_bufio_init(void) +{ + ao_bufio_setup(); + ao_sdcard_init(); ao_cmd_register(&ao_bufio_cmds[0]); } diff --git a/src/drivers/ao_bufio.h b/src/drivers/ao_bufio.h index c3bee906..6629f143 100644 --- a/src/drivers/ao_bufio.h +++ b/src/drivers/ao_bufio.h @@ -30,6 +30,9 @@ ao_bufio_flush_one(uint8_t *buf); void ao_bufio_flush(void); +void +ao_bufio_setup(void); + void ao_bufio_init(void); diff --git a/src/drivers/ao_fat.c b/src/drivers/ao_fat.c index 98f57d67..a19eff70 100644 --- a/src/drivers/ao_fat.c +++ b/src/drivers/ao_fat.c @@ -22,10 +22,26 @@ #include "ao_fat.h" #include "ao_bufio.h" +/* + * Basic file system types + */ + +typedef ao_fat_offset_t offset_t; +typedef ao_fat_sector_t sector_t; +typedef ao_fat_cluster_t cluster_t; +typedef ao_fat_dirent_t dirent_t; +typedef ao_fat_cluster_offset_t cluster_offset_t; + /* Partition information, sector numbers */ -static uint8_t partition_type; -static uint32_t partition_start, partition_end; +static uint8_t partition_type; +static sector_t partition_start, partition_end; + +#define AO_FAT_BAD_CLUSTER 0xffffff7 +#define AO_FAT_LAST_CLUSTER 0xfffffff +#define AO_FAT_IS_LAST_CLUSTER(c) (((c) & 0xffffff8) == 0xffffff8) +#define AO_FAT_IS_LAST_CLUSTER16(c) (((c) & 0xfff8) == 0xfff8) + #define SECTOR_SIZE 512 #define SECTOR_MASK (SECTOR_SIZE - 1) @@ -34,17 +50,25 @@ static uint32_t partition_start, partition_end; #define DIRENT_SIZE 32 /* File system parameters */ -static uint8_t sectors_per_cluster; -static uint32_t bytes_per_cluster; -static uint16_t reserved_sector_count; -static uint8_t number_fat; -static uint16_t root_entries; -static uint16_t sectors_per_fat; -static uint16_t number_cluster; -static uint32_t fat_start; -static uint32_t root_start; -static uint32_t data_start; -static uint16_t first_free_cluster; +static uint8_t sectors_per_cluster; +static uint32_t bytes_per_cluster; +static sector_t reserved_sector_count; +static uint8_t number_fat; +static dirent_t root_entries; +static sector_t sectors_per_fat; +static cluster_t number_cluster; +static sector_t fat_start; +static sector_t root_start; +static sector_t data_start; +static cluster_t next_free; +static uint8_t filesystem_full; + +/* FAT32 extra data */ +static uint8_t fat32; +static uint8_t fsinfo_dirty; +static cluster_t root_cluster; +static sector_t fsinfo_sector; +static cluster_t free_count; /* * Deal with LSB FAT data structures @@ -81,14 +105,14 @@ put_u16(uint8_t *base, uint16_t value) } static uint8_t -ao_fat_cluster_valid(uint16_t cluster) +ao_fat_cluster_valid(cluster_t cluster) { return (2 <= cluster && cluster < number_cluster); } /* Start using a sector */ static uint8_t * -ao_fat_sector_get(uint32_t sector) +ao_fat_sector_get(sector_t sector) { sector += partition_start; if (sector >= partition_end) @@ -99,49 +123,36 @@ ao_fat_sector_get(uint32_t sector) /* Finish using a sector, 'w' is 1 if modified */ #define ao_fat_sector_put(b,w) ao_bufio_put(b,w) -/* Start using a root directory entry */ -static uint8_t * -ao_fat_root_get(uint16_t e) -{ - uint32_t byte = e * DIRENT_SIZE; - uint32_t sector = byte >> SECTOR_SHIFT; - uint16_t offset = byte & SECTOR_MASK; - uint8_t *buf; - - buf = ao_fat_sector_get(root_start + sector); - if (!buf) - return NULL; - return buf + offset; -} - -/* Finish using a root directory entry, 'w' is 1 if modified */ -static void -ao_fat_root_put(uint8_t *root, uint16_t e, uint8_t write) -{ - uint16_t offset = ((e * DIRENT_SIZE) & SECTOR_MASK); - uint8_t *buf = root - offset; - - ao_fat_sector_put(buf, write); -} - /* Get the next cluster entry in the chain */ -static uint16_t -ao_fat_entry_read(uint16_t cluster) +static cluster_t +ao_fat_entry_read(cluster_t cluster) { - uint32_t sector; - uint16_t offset; + sector_t sector; + cluster_t offset; uint8_t *buf; - uint16_t ret; + cluster_t ret; if (!ao_fat_cluster_valid(cluster)) - return 0xfff7; - - sector = cluster >> (SECTOR_SHIFT - 1); - offset = (cluster << 1) & SECTOR_MASK; + return 0xfffffff7; + + if (fat32) + cluster <<= 2; + else + cluster <<= 1; + sector = cluster >> (SECTOR_SHIFT); + offset = cluster & SECTOR_MASK; buf = ao_fat_sector_get(fat_start + sector); if (!buf) return 0; - ret = get_u16(buf + offset); + + if (fat32) { + ret = get_u32(buf + offset); + ret &= 0xfffffff; + } else { + ret = get_u16(buf + offset); + if (AO_FAT_IS_LAST_CLUSTER16(ret)) + ret |= 0xfff0000; + } ao_fat_sector_put(buf, 0); return ret; } @@ -149,36 +160,60 @@ ao_fat_entry_read(uint16_t cluster) /* Replace the referenced cluster entry in the chain with * 'new_value'. Return the previous value. */ -static uint16_t -ao_fat_entry_replace(uint16_t cluster, uint16_t new_value) +static cluster_t +ao_fat_entry_replace(cluster_t cluster, cluster_t new_value) { - uint32_t sector; - uint16_t offset; - uint8_t *buf; - uint16_t ret; - uint8_t other_fats; + sector_t sector; + cluster_offset_t offset; + uint8_t *buf; + cluster_t ret; + cluster_t old_value; + uint8_t fat; if (!ao_fat_cluster_valid(cluster)) - return 0; - - sector = cluster >> (SECTOR_SHIFT - 1); - offset = (cluster << 1) & SECTOR_MASK; - buf = ao_fat_sector_get(fat_start + sector); - if (!buf) - return 0; - ret = get_u16(buf + offset); - put_u16(buf + offset, new_value); - ao_fat_sector_put(buf, 1); - - /* - * Keep the other FATs in sync - */ - for (other_fats = 1; other_fats < number_fat; other_fats++) { - buf = ao_fat_sector_get(fat_start + other_fats * sectors_per_fat + sector); - if (buf) { + return 0xfffffff7; + + /* Convert from cluster index to byte index */ + if (fat32) + cluster <<= 2; + else + cluster <<= 1; + sector = cluster >> SECTOR_SHIFT; + offset = cluster & SECTOR_MASK; + + new_value &= 0xfffffff; + for (fat = 0; fat < number_fat; fat++) { + buf = ao_fat_sector_get(fat_start + fat * sectors_per_fat + sector); + if (!buf) + return 0; + if (fat32) { + old_value = get_u32(buf + offset); + put_u32(buf + offset, new_value | (old_value & 0xf0000000)); + if (fat == 0) { + ret = old_value & 0xfffffff; + + /* Track the free count if it wasn't marked + * invalid when we mounted the file system + */ + if (free_count != 0xffffffff) { + if (new_value && !ret) { + --free_count; + fsinfo_dirty = 1; + } else if (!new_value && ret) { + ++free_count; + fsinfo_dirty = 1; + } + } + } + } else { + if (fat == 0) { + ret = get_u16(buf + offset); + if (AO_FAT_IS_LAST_CLUSTER16(ret)) + ret |= 0xfff0000; + } put_u16(buf + offset, new_value); - ao_fat_sector_put(buf, 1); } + ao_fat_sector_put(buf, 1); } return ret; @@ -189,12 +224,14 @@ ao_fat_entry_replace(uint16_t cluster, uint16_t new_value) * all of them as free */ static void -ao_fat_free_cluster_chain(uint16_t cluster) +ao_fat_free_cluster_chain(cluster_t cluster) { while (ao_fat_cluster_valid(cluster)) { - if (cluster < first_free_cluster) - first_free_cluster = cluster; - cluster = ao_fat_entry_replace(cluster, 0x0000); + if (cluster < next_free) { + next_free = cluster; + fsinfo_dirty = 1; + } + cluster = ao_fat_entry_replace(cluster, 0x00000000); } } @@ -207,8 +244,8 @@ ao_fat_free_cluster_chain(uint16_t cluster) * 0xffff if we walk off the end of the file or the cluster chain * is damaged somehow */ -static uint16_t -ao_fat_cluster_seek(uint16_t cluster, uint16_t distance) +static cluster_t +ao_fat_cluster_seek(cluster_t cluster, cluster_t distance) { while (distance) { cluster = ao_fat_entry_read(cluster); @@ -219,6 +256,176 @@ ao_fat_cluster_seek(uint16_t cluster, uint16_t distance) return cluster; } +/* + * ao_fat_cluster_set_size + * + * Set the number of clusters in the specified chain, + * freeing extra ones or alocating new ones as needed + * + * Returns AO_FAT_BAD_CLUSTER on allocation failure + */ + +static cluster_t +ao_fat_cluster_set_size(cluster_t first_cluster, cluster_t size) +{ + cluster_t clear_cluster = 0; + + if (size == 0) { + clear_cluster = first_cluster; + first_cluster = 0; + } else { + cluster_t have; + cluster_t last_cluster = 0; + cluster_t next_cluster; + + /* Walk the cluster chain to the + * spot where it needs to change. That + * will either be the end of the chain (in case it needs to grow), + * or after the desired number of clusters, in which case it needs to shrink + */ + next_cluster = first_cluster; + for (have = 0; have < size; have++) { + last_cluster = next_cluster; + next_cluster = ao_fat_entry_read(last_cluster); + if (!ao_fat_cluster_valid(next_cluster)) + break; + } + + if (have == size) { + /* The file is large enough, truncate as needed */ + if (ao_fat_cluster_valid(next_cluster)) { + /* Rewrite that cluster entry with 0xffff to mark the end of the chain */ + clear_cluster = ao_fat_entry_replace(last_cluster, AO_FAT_LAST_CLUSTER); + filesystem_full = 0; + } else { + /* The chain is already the right length, don't mess with it */ + ; + } + } else { + cluster_t need; + cluster_t free; + + if (filesystem_full) + return AO_FAT_BAD_CLUSTER; + + if (next_free < 2 || number_cluster <= next_free) { + next_free = 2; + fsinfo_dirty = 1; + } + + /* See if there are enough free clusters in the file system */ + need = size - have; + +#define loop_cluster for (free = next_free; need > 0;) +#define next_cluster \ + if (++free == number_cluster) \ + free = 2; \ + if (free == next_free) \ + break; \ + + loop_cluster { + if (!ao_fat_entry_read(free)) + need--; + next_cluster; + } + /* Still need some, tell the user that we've failed */ + if (need) { + filesystem_full = 1; + return AO_FAT_BAD_CLUSTER; + } + + /* Now go allocate those clusters and + * thread them onto the chain + */ + need = size - have; + loop_cluster { + if (!ao_fat_entry_read(free)) { + next_free = free + 1; + if (next_free >= number_cluster) + next_free = 2; + fsinfo_dirty = 1; + if (last_cluster) + ao_fat_entry_replace(last_cluster, free); + else + first_cluster = free; + last_cluster = free; + need--; + } + next_cluster; + } +#undef loop_cluster +#undef next_cluster + /* Mark the new end of the chain */ + ao_fat_entry_replace(last_cluster, AO_FAT_LAST_CLUSTER); + } + } + + /* Deallocate clusters off the end of the file */ + if (ao_fat_cluster_valid(clear_cluster)) + ao_fat_free_cluster_chain(clear_cluster); + return first_cluster; +} + +/* Start using a root directory entry */ +static uint8_t * +ao_fat_root_get(dirent_t e) +{ + offset_t byte = e * DIRENT_SIZE; + sector_t sector = byte >> SECTOR_SHIFT; + cluster_offset_t offset = byte & SECTOR_MASK; + uint8_t *buf; + + if (fat32) { + cluster_t cluster_distance = sector / sectors_per_cluster; + sector_t sector_index = sector % sectors_per_cluster; + cluster_t cluster = ao_fat_cluster_seek(root_cluster, cluster_distance); + + if (ao_fat_cluster_valid(cluster)) + sector = data_start + (cluster-2) * sectors_per_cluster + sector_index; + else + return NULL; + } else { + if (e >= root_entries) + return NULL; + sector = root_start + sector; + } + + buf = ao_fat_sector_get(sector); + if (!buf) + return NULL; + return buf + offset; +} + +/* Finish using a root directory entry, 'w' is 1 if modified */ +static void +ao_fat_root_put(uint8_t *root, dirent_t e, uint8_t write) +{ + cluster_offset_t offset = ((e * DIRENT_SIZE) & SECTOR_MASK); + uint8_t *buf = root - offset; + + ao_fat_sector_put(buf, write); +} + +/* + * ao_fat_root_extend + * + * On FAT32, make the + */ +static int8_t +ao_fat_root_extend(dirent_t ents) +{ + offset_t byte_size; + cluster_t cluster_size; + if (!fat32) + return 0; + + byte_size = ents * 0x20; + cluster_size = byte_size / bytes_per_cluster; + if (ao_fat_cluster_set_size(root_cluster, cluster_size) != AO_FAT_BAD_CLUSTER) + return 1; + return 0; +} + /* * ao_fat_setup_partition * @@ -316,6 +523,26 @@ ao_fat_setup_fs(void) number_fat = boot[0x10]; root_entries = get_u16(boot + 0x11); sectors_per_fat = get_u16(boot+0x16); + fat32 = 0; + if (sectors_per_fat == 0) { + fat32 = 1; + sectors_per_fat = get_u32(boot+0x24); + root_cluster = get_u32(boot+0x2c); + fsinfo_sector = get_u16(boot + 0x30); + } + ao_fat_sector_put(boot, 0); + + free_count = 0xffffffff; + next_free = 0; + if (fat32 && fsinfo_sector) { + uint8_t *fsinfo = ao_fat_sector_get(fsinfo_sector); + + if (fsinfo) { + free_count = get_u32(fsinfo + 0x1e8); + next_free = get_u32(fsinfo + 0x1ec); + ao_fat_sector_put(fsinfo, 0); + } + } fat_start = reserved_sector_count;; root_start = fat_start + number_fat * sectors_per_fat; @@ -325,6 +552,7 @@ ao_fat_setup_fs(void) number_cluster = data_sectors / sectors_per_cluster; + printf ("fat32: %d\n", fat32); printf ("sectors per cluster %d\n", sectors_per_cluster); printf ("reserved sectors %d\n", reserved_sector_count); printf ("number of FATs %d\n", number_fat); @@ -335,20 +563,35 @@ ao_fat_setup_fs(void) printf ("root start %d\n", root_start); printf ("data start %d\n", data_start); - ao_fat_sector_put(boot, 0); - return 1; } +/* + * State for the current opened file + */ +static struct ao_fat_dirent ao_file_dirent; +static uint32_t ao_file_offset; +static uint32_t ao_file_cluster_offset; +static cluster_t ao_file_cluster; +static uint8_t ao_file_opened; + static uint8_t ao_fat_setup(void) { + ao_bufio_setup(); + + partition_type = partition_start = partition_end = 0; + sectors_per_cluster = bytes_per_cluster = reserved_sector_count = 0; + number_fat = root_entries = sectors_per_fat = 0; + number_cluster = fat_start = root_start = data_start = 0; + next_free = filesystem_full = 0; + fat32 = fsinfo_dirty = root_cluster = fsinfo_sector = free_count = 0; + memset(&ao_file_dirent, '\0', sizeof (ao_file_dirent)); + ao_file_offset = ao_file_cluster_offset = ao_file_cluster = ao_file_opened = 0; if (!ao_fat_setup_partition()) return 0; - check_bufio("partition setup"); if (!ao_fat_setup_fs()) return 0; - check_bufio("fs setup"); return 1; } @@ -356,19 +599,13 @@ ao_fat_setup(void) * Basic file operations */ -static struct ao_fat_dirent ao_file_dirent; -static uint32_t ao_file_offset; -static uint32_t ao_file_cluster_offset; -static uint16_t ao_file_cluster; -static uint8_t ao_file_opened; - static uint32_t ao_fat_current_sector(void) { - uint16_t cluster_offset; + cluster_t cluster_offset; uint32_t sector_offset; uint16_t sector_index; - uint16_t cluster; + cluster_t cluster; if (ao_file_offset > ao_file_dirent.size) return 0xffffffff; @@ -381,7 +618,7 @@ ao_fat_current_sector(void) } if (ao_file_cluster_offset + bytes_per_cluster <= ao_file_offset) { - uint16_t cluster_distance; + cluster_t cluster_distance; cluster_offset = sector_offset / sectors_per_cluster; @@ -414,98 +651,44 @@ ao_fat_set_offset(uint32_t offset) static int8_t ao_fat_set_size(uint32_t size) { - uint16_t clear_cluster = 0; uint8_t *dent; - uint16_t first_cluster; + cluster_t first_cluster; + cluster_t have_clusters, need_clusters; - first_cluster = ao_file_dirent.cluster; if (size == ao_file_dirent.size) return AO_FAT_SUCCESS; - if (size == 0) { - clear_cluster = ao_file_dirent.cluster; - first_cluster = 0; - } else { - uint16_t new_num; - uint16_t old_num; - - new_num = (size + bytes_per_cluster - 1) / bytes_per_cluster; - old_num = (ao_file_dirent.size + bytes_per_cluster - 1) / bytes_per_cluster; - if (new_num < old_num) { - uint16_t last_cluster; - - /* Go find the last cluster we want to preserve in the file */ - last_cluster = ao_fat_cluster_seek(ao_file_dirent.cluster, new_num - 1); - - /* Rewrite that cluster entry with 0xffff to mark the end of the chain */ - clear_cluster = ao_fat_entry_replace(last_cluster, 0xffff); - } else if (new_num > old_num) { - uint16_t need; - uint16_t free; - uint16_t last_cluster; - uint16_t highest_allocated = 0; - - if (old_num) - last_cluster = ao_fat_cluster_seek(ao_file_dirent.cluster, old_num - 1); - else - last_cluster = 0; - if (first_free_cluster < 2 || number_cluster <= first_free_cluster) - first_free_cluster = 2; + first_cluster = ao_file_dirent.cluster; + have_clusters = (ao_file_dirent.size + bytes_per_cluster - 1) / bytes_per_cluster; + need_clusters = (size + bytes_per_cluster - 1) / bytes_per_cluster; - /* See if there are enough free clusters in the file system */ - need = new_num - old_num; + if (have_clusters != need_clusters) { + if (ao_file_cluster && size >= ao_file_cluster_offset) { + cluster_t offset_clusters = (ao_file_cluster_offset + bytes_per_cluster) / bytes_per_cluster; + cluster_t extra_clusters = need_clusters - offset_clusters; + cluster_t next_cluster; -#define loop_cluster for (free = first_free_cluster; need > 0;) -#define next_cluster \ - if (++free == number_cluster) \ - free = 2; \ - if (free == first_free_cluster) \ - break; \ - - loop_cluster { - if (!ao_fat_entry_read(free)) - need--; - next_cluster; - } - /* Still need some, tell the user that we've failed */ - if (need) + next_cluster = ao_fat_cluster_set_size(ao_file_cluster, extra_clusters); + if (next_cluster == AO_FAT_BAD_CLUSTER) return -AO_FAT_ENOSPC; + } else { + first_cluster = ao_fat_cluster_set_size(first_cluster, need_clusters); - /* Now go allocate those clusters */ - need = new_num - old_num; - loop_cluster { - if (!ao_fat_entry_read(free)) { - if (free > highest_allocated) - highest_allocated = free; - if (last_cluster) - ao_fat_entry_replace(last_cluster, free); - else - first_cluster = free; - last_cluster = free; - need--; - } - next_cluster; - } - first_free_cluster = highest_allocated + 1; - if (first_free_cluster >= number_cluster) - first_free_cluster = 2; - - /* Mark the new end of the chain */ - ao_fat_entry_replace(last_cluster, 0xffff); + if (first_cluster == AO_FAT_BAD_CLUSTER) + return -AO_FAT_ENOSPC; } } - /* Deallocate clusters off the end of the file */ - if (ao_fat_cluster_valid(clear_cluster)) - ao_fat_free_cluster_chain(clear_cluster); - /* Update the directory entry */ dent = ao_fat_root_get(ao_file_dirent.entry); if (!dent) return -AO_FAT_EIO; put_u32(dent + 0x1c, size); put_u16(dent + 0x1a, first_cluster); + if (fat32) + put_u16(dent + 0x14, first_cluster >> 16); ao_fat_root_put(dent, ao_file_dirent.entry, 1); + ao_file_dirent.size = size; ao_file_dirent.cluster = first_cluster; return AO_FAT_SUCCESS; @@ -556,9 +739,39 @@ ao_fat_dirent_init(uint8_t *dent, uint16_t entry, struct ao_fat_dirent *dirent) dirent->attr = dent[0x0b]; dirent->size = get_u32(dent+0x1c); dirent->cluster = get_u16(dent+0x1a); + if (fat32) + dirent->cluster |= (cluster_t) get_u16(dent + 0x14) << 16; dirent->entry = entry; } +/* + * ao_fat_flush_fsinfo + * + * Write out any fsinfo changes to disk + */ + +void +ao_fat_flush_fsinfo(void) +{ + uint8_t *fsinfo; + + if (!fat32) + return; + + if (!fsinfo_dirty) + return; + fsinfo_dirty = 0; + if (!fsinfo_sector) + return; + + fsinfo = ao_fat_sector_get(fsinfo_sector); + if (fsinfo) { + put_u32(fsinfo + 0x1e8, free_count); + put_u32(fsinfo + 0x1ec, next_free); + ao_fat_sector_put(fsinfo, 1); + } +} + /* * Public API */ @@ -605,6 +818,7 @@ ao_fat_creat(char name[11]) { uint16_t entry; int8_t status; + uint8_t *dent; if (ao_file_opened) return -AO_FAT_EMFILE; @@ -616,12 +830,14 @@ ao_fat_creat(char name[11]) status = ao_fat_set_size(0); break; case -AO_FAT_ENOENT: - for (entry = 0; entry < root_entries; entry++) { - uint8_t *dent = ao_fat_root_get(entry); - + entry = 0; + for (;;) { + dent = ao_fat_root_get(entry); if (!dent) { - status = -AO_FAT_EIO; - ao_fat_root_put(dent, entry, 0); + + if (ao_fat_root_extend(entry)) + continue; + status = -AO_FAT_ENOSPC; break; } @@ -636,9 +852,8 @@ ao_fat_creat(char name[11]) } else { ao_fat_root_put(dent, entry, 0); } + entry++; } - if (entry == root_entries) - status = -AO_FAT_ENOSPC; } return status; } @@ -658,6 +873,8 @@ ao_fat_close(void) ao_file_offset = 0; ao_file_cluster = 0; ao_file_opened = 0; + + ao_fat_flush_fsinfo(); ao_bufio_flush(); return AO_FAT_SUCCESS; } @@ -849,10 +1066,10 @@ ao_fat_readdir(uint16_t *entry, struct ao_fat_dirent *dirent) { uint8_t *dent; - if (*entry >= root_entries) - return 0; for (;;) { dent = ao_fat_root_get(*entry); + if (!dent) + return 0; if (dent[0] == AO_FAT_DENT_END) { ao_fat_root_put(dent, *entry, 0); diff --git a/src/drivers/ao_fat.h b/src/drivers/ao_fat.h index 5b9b300f..cfe98a76 100644 --- a/src/drivers/ao_fat.h +++ b/src/drivers/ao_fat.h @@ -32,8 +32,8 @@ ao_fat_init(void); #define AO_FAT_DENT_EMPTY 0xe5 #define AO_FAT_DENT_END 0x00 -#define AO_FAT_IS_FILE(attr) (((attr) & (AO_FAT_FILE_VOLUME_LABEL|AO_FAT_FILE_DIRECTORY|AO_FAT_FILE_ARCHIVE)) == 0) -#define AO_FAT_IS_DIR(attr) (((attr) & (AO_FAT_FILE_DIRECTORY)) == AO_FAT_FILE_DIRECTORY) +#define AO_FAT_IS_FILE(attr) (((attr) & (AO_FAT_FILE_VOLUME_LABEL|AO_FAT_FILE_DIRECTORY)) == 0) +#define AO_FAT_IS_DIR(attr) (((attr) & (AO_FAT_FILE_DIRECTORY|AO_FAT_FILE_VOLUME_LABEL)) == AO_FAT_FILE_DIRECTORY) #define AO_FAT_SUCCESS 0 #define AO_FAT_EPERM 1 @@ -80,12 +80,37 @@ ao_fat_unlink(char name[11]); int8_t ao_fat_rename(char old[11], char new[11]); +/* + * Byte offset within a file. Supports files up to 2GB in size + */ +typedef int32_t ao_fat_offset_t; + +/* + * Cluster index in partition data space + */ +typedef uint32_t ao_fat_cluster_t; + +/* + * Sector offset within partition + */ +typedef uint32_t ao_fat_sector_t; + +/* + * Index within the root directory + */ +typedef uint16_t ao_fat_dirent_t; + +/* + * Offset within a cluster (or sector) + */ +typedef uint16_t ao_fat_cluster_offset_t; + struct ao_fat_dirent { - char name[11]; - uint8_t attr; - uint32_t size; - uint16_t cluster; - uint16_t entry; + char name[11]; + uint8_t attr; + uint32_t size; + ao_fat_cluster_t cluster; + uint16_t entry; }; int8_t diff --git a/src/test/ao_fat_test.c b/src/test/ao_fat_test.c index fffd5af4..48d5d8a4 100644 --- a/src/test/ao_fat_test.c +++ b/src/test/ao_fat_test.c @@ -84,14 +84,33 @@ ao_sdcard_write_block(uint32_t block, uint8_t *data) return write(fs_fd, data, 512) == 512; } -char *fs = "fs.fat"; +struct fs_param { + int fat; + int blocks; +} fs_params[] = { + { .fat = 16, .blocks = 16384 }, + { .fat = 32, .blocks = 16384 }, + { .fat = 16, .blocks = 65536 }, + { .fat = 32, .blocks = 65536 }, + { .fat = 16, .blocks = 1048576 }, + { .fat = 32, .blocks = 1048576 }, + { .fat = 0, .blocks = 0 }, +}; + +char *fs = "fs.fat"; +struct fs_param *param; void ao_sdcard_init(void) { char cmd[1024]; - snprintf(cmd, sizeof(cmd), "rm -f %s && mkfs.vfat -C %s 16384", fs, fs); + if (fs_fd) { + close(fs_fd); + fs_fd = 0; + } + snprintf(cmd, sizeof(cmd), "rm -f %s && mkfs.vfat -F %d -C %s %d", + fs, param->fat, fs, param->blocks); if (system (cmd) != 0) { fprintf(stderr, "'%s' failed\n", cmd); exit(1); @@ -125,21 +144,27 @@ check_fat(void); #include "ao_fat.c" /* Get the next cluster entry in the chain */ -static uint16_t -ao_fat_entry_raw_read(uint16_t cluster, uint8_t fat) +static cluster_t +ao_fat_entry_raw_read(cluster_t cluster, uint8_t fat) { - uint32_t sector; - uint16_t offset; - uint8_t *buf; - uint16_t ret; - -// cluster -= 2; - sector = cluster >> (SECTOR_SHIFT - 1); - offset = (cluster << 1) & SECTOR_MASK; + sector_t sector; + cluster_offset_t offset; + uint8_t *buf; + cluster_t ret; + + if (fat32) + cluster <<= 2; + else + cluster <<= 1; + sector = cluster >> SECTOR_SHIFT; + offset = cluster & SECTOR_MASK; buf = ao_fat_sector_get(fat_start + fat * sectors_per_fat + sector); if (!buf) return 0; - ret = get_u16(buf + offset); + if (fat32) + ret = get_u32(buf + offset); + else + ret = get_u16(buf + offset); ao_fat_sector_put(buf, 0); return ret; } @@ -153,16 +178,21 @@ dump_fat(void) for (e = 0; e < number_cluster; e++) { if ((e & 0xf) == 0x0) printf ("%04x: ", e); - printf (" %04x", ao_fat_entry_raw_read(e, 0)); + if (fat32) + printf (" %08x", ao_fat_entry_raw_read(e, 0)); + else + printf (" %04x", ao_fat_entry_raw_read(e, 0)); if ((e & 0xf) == 0xf) putchar ('\n'); } + if (e & 0xf) + putchar('\n'); } void fat_list(void) { - uint16_t entry = 0; + dirent_t entry = 0; struct ao_fat_dirent dirent; printf (" **** Root directory ****\n"); @@ -182,8 +212,8 @@ fat_list(void) void fatal(char *msg, ...) { - dump_fat(); - fat_list(); +// dump_fat(); +// fat_list(); va_list l; va_start(l, msg); @@ -200,7 +230,7 @@ check_fat(void) int f; for (e = 0; e < number_cluster; e++) { - uint16_t v = ao_fat_entry_raw_read(e, 0); + cluster_t v = ao_fat_entry_raw_read(e, 0); for (f = 1; f < number_fat; f++) { if (ao_fat_entry_raw_read(e, f) != v) fatal ("fats differ at %d\n", e); @@ -208,24 +238,24 @@ check_fat(void) } } -uint16_t -check_file(uint16_t dent, uint16_t first_cluster, uint8_t *used) +cluster_t +check_file(dirent_t dent, cluster_t first_cluster, dirent_t *used) { - uint16_t clusters = 0; - uint16_t cluster; + cluster_t clusters = 0; + cluster_t cluster; if (!first_cluster) return 0; for (cluster = first_cluster; - (cluster & 0xfff8) != 0xfff8; + fat32 ? !AO_FAT_IS_LAST_CLUSTER(cluster) : !AO_FAT_IS_LAST_CLUSTER16(cluster); cluster = ao_fat_entry_raw_read(cluster, 0)) { if (!ao_fat_cluster_valid(cluster)) - fatal("file %d: invalid cluster %04x\n", dent, cluster); + fatal("file %d: invalid cluster %08x\n", dent, cluster); if (used[cluster]) - fatal("file %d: duplicate cluster %04x\n", dent, cluster); - used[cluster] = 1; + fatal("file %d: duplicate cluster %08x also in file %d\n", dent, cluster, used[cluster]-1); + used[cluster] = dent; clusters++; } return clusters; @@ -234,25 +264,27 @@ check_file(uint16_t dent, uint16_t first_cluster, uint8_t *used) void check_fs(void) { - uint16_t r; - uint16_t cluster, chain; - uint8_t *used; + dirent_t r; + cluster_t cluster, chain; + dirent_t *used; + uint8_t *dent; check_fat(); - used = calloc(1, number_cluster); + used = calloc(sizeof (dirent_t), number_cluster); - for (r = 0; r < root_entries; r++) { - uint8_t *dent = ao_fat_root_get(r); - uint16_t clusters; - uint32_t size; - uint16_t first_cluster; - uint8_t name[11]; + for (r = 0; (dent = ao_fat_root_get(r)); r++) { + cluster_t clusters; + offset_t size; + cluster_t first_cluster; + char name[11]; if (!dent) fatal("cannot map dent %d\n", r); memcpy(name, dent+0, 11); first_cluster = get_u16(dent + 0x1a); + if (fat32) + first_cluster |= (cluster_t) get_u16(dent + 0x14) << 16; size = get_u32(dent + 0x1c); ao_fat_root_put(dent, r, 0); @@ -260,7 +292,7 @@ check_fs(void) break; } - clusters = check_file(r, first_cluster, used); + clusters = check_file(r + 1, first_cluster, used); if (size == 0) { if (clusters != 0) fatal("file %d: zero sized, but %d clusters\n", clusters); @@ -273,20 +305,29 @@ check_fs(void) r, size, clusters, clusters * bytes_per_cluster); } } - for (; r < root_entries; r++) { - uint8_t *dent = ao_fat_root_get(r); - if (!dent) - fatal("cannot map dent %d\n", r); - if (dent[0] != AO_FAT_DENT_END) - fatal("found non-zero dent past end %d\n", r); - ao_fat_root_put(dent, r, 0); + if (!fat32) { + for (; r < root_entries; r++) { + uint8_t *dent = ao_fat_root_get(r); + if (!dent) + fatal("cannot map dent %d\n", r); + if (dent[0] != AO_FAT_DENT_END) + fatal("found non-zero dent past end %d\n", r); + ao_fat_root_put(dent, r, 0); + } + } else { + check_file((dirent_t) -1, root_cluster, used); } for (cluster = 0; cluster < 2; cluster++) { chain = ao_fat_entry_raw_read(cluster, 0); - if ((chain & 0xfff8) != 0xfff8) - fatal("cluster %d: not marked busy\n", cluster); + if (fat32) { + if ((chain & 0xffffff8) != 0xffffff8) + fatal("cluster %d: not marked busy\n", cluster); + } else { + if ((chain & 0xfff8) != 0xfff8) + fatal("cluster %d: not marked busy\n", cluster); + } } for (; cluster < number_cluster; cluster++) { chain = ao_fat_entry_raw_read(cluster, 0); @@ -296,40 +337,66 @@ check_fs(void) fatal("cluster %d: marked busy, but not in any file\n", cluster); } else { if (used[cluster] != 0) - fatal("cluster %d: marked free, but foudn in file\n", cluster); + fatal("cluster %d: marked free, but found in file %d\n", cluster, used[cluster]-1); } } } -#define NUM_FILES 10 -#define LINES_FILE 80000 +#define NUM_FILES 100 +#define LINES_FILE 500000 uint32_t sizes[NUM_FILES]; unsigned char md5[NUM_FILES][MD5_DIGEST_LENGTH]; -int -main(int argc, char **argv) +void +short_test_fs(void) +{ + int len; + char buf[345]; + + if (ao_fat_open("HELLO TXT",AO_FAT_OPEN_READ) == AO_FAT_SUCCESS) { + printf ("File contents for HELLO.TXT\n"); + while ((len = ao_fat_read(buf, sizeof(buf)))) + write(1, buf, len); + ao_fat_close(); + } + + if (ao_fat_creat("NEWFILE TXT") == AO_FAT_SUCCESS) { + printf ("Create new file\n"); + for (len = 0; len < 2; len++) + ao_fat_write("hello, world!\n", 14); + ao_fat_seek(0, AO_FAT_SEEK_SET); + printf ("read new file\n"); + while ((len = ao_fat_read(buf, sizeof (buf)))) + write (1, buf, len); + ao_fat_close(); + } + + check_fs(); +} + +void +long_test_fs(void) { char name[12]; int id; MD5_CTX ctx; unsigned char md5_check[MD5_DIGEST_LENGTH]; + char buf[337]; + int len; + uint64_t total_file_size = 0; - if (argv[1]) - fs = argv[1]; - - ao_fat_init(); - - check_bufio("top"); - ao_fat_setup(); + total_reads = total_writes = 0; - check_fs(); - check_bufio("after setup"); printf (" **** Creating %d files\n", NUM_FILES); + memset(sizes, '\0', sizeof (sizes)); for (id = 0; id < NUM_FILES; id++) { sprintf(name, "D%07dTXT", id); + if ((id % (NUM_FILES/50)) == 0) { + printf ("."); fflush(stdout); + } if (ao_fat_creat(name) == AO_FAT_SUCCESS) { int j; char line[64]; @@ -342,6 +409,7 @@ main(int argc, char **argv) ret = ao_fat_write((uint8_t *) line, len); if (ret <= 0) break; + total_file_size += ret; MD5_Update(&ctx, line, ret); sizes[id] += ret; if (ret != len) @@ -353,20 +421,24 @@ main(int argc, char **argv) } } + printf ("\n **** Write IO: read %llu write %llu data sectors %llu\n", total_reads, total_writes, (total_file_size + 511) / 512); + check_bufio("all files created"); printf (" **** All done creating files\n"); check_fs(); + total_reads = total_writes = 0; + printf (" **** Comparing %d files\n", NUM_FILES); for (id = 0; id < NUM_FILES; id++) { - char buf[337]; uint32_t size; sprintf(name, "D%07dTXT", id); size = 0; + if ((id % (NUM_FILES/50)) == 0) { + printf ("."); fflush(stdout); + } if (ao_fat_open(name, AO_FAT_OPEN_READ) == AO_FAT_SUCCESS) { - int len; - MD5_Init(&ctx); while ((len = ao_fat_read((uint8_t *) buf, sizeof(buf))) > 0) { MD5_Update(&ctx, buf, len); @@ -382,7 +454,43 @@ main(int argc, char **argv) check_bufio("file shown"); } } + printf ("\n **** Read IO: read %llu write %llu\n", total_reads, total_writes); +} + +char *params[] = { + "-F 16 -C %s 16384", + "-F 32 -C %s 16384", + "-F 16 -C %s 65536", + "-F 32 -C %s 65536", + "-F 16 -C %s 1048576", + "-F 32 -C %s 1048576", + NULL +}; + +int +main(int argc, char **argv) +{ + int p; + + if (argv[1]) + fs = argv[1]; + + for (p = 0; fs_params[p].fat; p++) { + param = &fs_params[p]; + ao_fat_init(); + + check_bufio("top"); + ao_fat_setup(); + + check_fs(); + check_bufio("after setup"); + +#ifdef SIMPLE_TEST + short_test_fs(); +#else + long_test_fs(); +#endif + } - printf ("\n **** Total IO: read %llu write %llu\n", total_reads, total_writes); return 0; } -- cgit v1.2.3 From 93a9aa703a0173e13b327ed432e6d52e90ebfa1b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 29 Mar 2013 17:05:36 -0700 Subject: altos: Get CC115L radio working. This involved figuring out which GPIO signal would reliably indicate that the transmitter was finished; I ended up using the PA_PD bit for this. This also converts all of the radio users to the long packet support as the CC115L has only a 64-byte fifo, not large enough to hold either an RDF tone or a regular AltOS telemetry packet. This also renames the public API for sending APRS packets from ao_radio_send_lots to ao_radio_send_aprs, which is at least more accurate. The workings of that API haven't changed, just the name. Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- src/drivers/ao_aprs.c | 2 +- src/drivers/ao_cc1120.c | 2 +- src/drivers/ao_cc115l.c | 544 +++++++++++++++++++++++++-------------------- src/drivers/ao_rf_cc115l.h | 83 ------- src/telegps-v0.1/Makefile | 1 - src/telegps-v0.1/ao_pins.h | 16 +- src/test/ao_aprs_test.c | 2 +- 8 files changed, 312 insertions(+), 340 deletions(-) delete mode 100644 src/drivers/ao_rf_cc115l.h (limited to 'src/test') diff --git a/src/core/ao.h b/src/core/ao.h index 7c5c69b8..e3161b4c 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -544,7 +544,7 @@ ao_radio_test(uint8_t on); typedef int16_t (*ao_radio_fill_func)(uint8_t *buffer, int16_t len); void -ao_radio_send_lots(ao_radio_fill_func fill); +ao_radio_send_aprs(ao_radio_fill_func fill); /* * ao_radio_pa diff --git a/src/drivers/ao_aprs.c b/src/drivers/ao_aprs.c index 03bcab05..6ab61e6a 100644 --- a/src/drivers/ao_aprs.c +++ b/src/drivers/ao_aprs.c @@ -593,7 +593,7 @@ void ao_aprs_send(void) tncIndex = 0; tncMode = TNC_TX_SYNC; - ao_radio_send_lots(tncFill); + ao_radio_send_aprs(tncFill); } /** @} */ diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 53bb5a62..a26eccbc 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -747,7 +747,7 @@ ao_radio_send(const void *d, uint8_t size) #define AO_RADIO_LOTS 64 void -ao_radio_send_lots(ao_radio_fill_func fill) +ao_radio_send_aprs(ao_radio_fill_func fill) { uint8_t buf[AO_RADIO_LOTS], *b; int cnt; diff --git a/src/drivers/ao_cc115l.c b/src/drivers/ao_cc115l.c index 5b0ec3d7..1d8211f6 100644 --- a/src/drivers/ao_cc115l.c +++ b/src/drivers/ao_cc115l.c @@ -25,13 +25,18 @@ static uint8_t ao_radio_mutex; -static uint8_t ao_radio_wake; /* radio ready. Also used as sleep address */ +static uint8_t ao_radio_fifo; /* fifo drained interrupt received */ +static uint8_t ao_radio_done; /* tx done interrupt received */ +static uint8_t ao_radio_wake; /* sleep address for radio interrupts */ static uint8_t ao_radio_abort; /* radio operation should abort */ static uint8_t ao_radio_mcu_wake; /* MARC status change */ static uint8_t ao_radio_marcstate; /* Last read MARC state value */ +/* Debugging commands */ #define CC115L_DEBUG 1 -#define CC115L_TRACE 1 + +/* Runtime tracing */ +#define CC115L_TRACE 0 #define FOSC 26000000 @@ -42,15 +47,67 @@ static uint8_t ao_radio_marcstate; /* Last read MARC state value */ #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC115L_SPI_BUS) #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC115L_SPI_BUS) +struct ao_cc115l_reg { + uint16_t addr; + char *name; +}; + +#if CC115L_TRACE + +const static struct ao_cc115l_reg ao_cc115l_reg[]; +const static char *cc115l_state_name[]; + +enum ao_cc115l_trace_type { + trace_strobe, + trace_read, + trace_write, + trace_dma, + trace_line, +}; + +struct ao_cc115l_trace { + enum ao_cc115l_trace_type type; + int16_t addr; + int16_t value; + const char *comment; +}; + +#define NUM_TRACE 256 + +static struct ao_cc115l_trace trace[NUM_TRACE]; +static int trace_i; +static int trace_disable; + +static void trace_add(enum ao_cc115l_trace_type type, int16_t addr, int16_t value, const char *comment) +{ + if (trace_disable) + return; + switch (type) { + case trace_read: + case trace_write: + comment = ao_cc115l_reg[addr].name; + break; + case trace_strobe: + comment = cc115l_state_name[(value >> 4) & 0x7]; + break; + } + trace[trace_i].type = type; + trace[trace_i].addr = addr; + trace[trace_i].value = value; + trace[trace_i].comment = comment; + if (++trace_i == NUM_TRACE) + trace_i = 0; +} +#else +#define trace_add(t,a,v,c) +#endif + static uint8_t -ao_radio_reg_read(uint16_t addr) +ao_radio_reg_read(uint8_t addr) { uint8_t data[1]; uint8_t d; -#if CC115L_TRACE - printf("\t\tao_radio_reg_read (%04x): ", addr); flush(); -#endif data[0] = ((1 << CC115L_READ) | (0 << CC115L_BURST) | addr); @@ -58,21 +115,17 @@ ao_radio_reg_read(uint16_t addr) ao_radio_spi_send(data, 1); ao_radio_spi_recv(data, 1); ao_radio_deselect(); -#if CC115L_TRACE - printf (" %02x\n", data[0]); -#endif + trace_add(trace_read, addr, data[0], NULL); return data[0]; } static void -ao_radio_reg_write(uint16_t addr, uint8_t value) +ao_radio_reg_write(uint8_t addr, uint8_t value) { uint8_t data[2]; uint8_t d; -#if CC115L_TRACE - printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value); -#endif + trace_add(trace_write, addr, value, NULL); data[0] = ((0 << CC115L_READ) | (0 << CC115L_BURST) | addr); @@ -107,15 +160,10 @@ ao_radio_strobe(uint8_t addr) { uint8_t in; -#if CC115L_TRACE - printf("\t\tao_radio_strobe (%02x): ", addr); flush(); -#endif ao_radio_select(); ao_radio_duplex(&addr, &in, 1); ao_radio_deselect(); -#if CC115L_TRACE - printf("%02x\n", in); flush(); -#endif + trace_add(trace_strobe, addr, in, NULL); return in; } @@ -141,25 +189,11 @@ static uint8_t ao_radio_fifo_write(uint8_t *data, uint8_t len) { uint8_t status = ao_radio_fifo_write_start(); -#if CC115L_TRACE - printf ("fifo_write %d\n", len); -#endif + trace_add(trace_dma, CC115L_FIFO, len, NULL); ao_radio_spi_send(data, len); return ao_radio_fifo_write_stop(status); } -static uint8_t -ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) -{ - uint8_t status = ao_radio_fifo_write_start(); - -#if CC115L_TRACE - printf ("fifo_write_fixed %02x %d\n", data, len); -#endif - ao_radio_spi_send_fixed(data, len); - return ao_radio_fifo_write_stop(status); -} - static uint8_t ao_radio_tx_fifo_space(void) { @@ -179,42 +213,28 @@ ao_radio_get_marcstate(void) { return ao_radio_reg_read(CC115L_MARCSTATE) & CC115L_MARCSTATE_MASK; } - + static void -ao_radio_mcu_wakeup_isr(void) +ao_radio_done_isr(void) { - ao_radio_mcu_wake = 1; + ao_exti_disable(AO_CC115L_DONE_INT_PORT, AO_CC115L_DONE_INT_PIN); + trace_add(trace_line, __LINE__, 0, "done_isr"); + ao_radio_done = 1; ao_wakeup(&ao_radio_wake); } - -static void -ao_radio_check_marcstate(void) -{ - ao_radio_mcu_wake = 0; - ao_radio_marcstate = ao_radio_get_marcstate(); - - /* Anyt other than 'tx finished' means an error occurred */ - if (ao_radio_marcstate != CC115L_MARCSTATE_TX_END) - ao_radio_abort = 1; -} - static void -ao_radio_isr(void) +ao_radio_fifo_isr(void) { - ao_exti_disable(AO_CC115L_INT_PORT, AO_CC115L_INT_PIN); - ao_radio_wake = 1; + ao_exti_disable(AO_CC115L_FIFO_INT_PORT, AO_CC115L_FIFO_INT_PIN); + trace_add(trace_line, __LINE__, 0, "fifo_isr"); + ao_radio_fifo = 1; ao_wakeup(&ao_radio_wake); } static void ao_radio_start_tx(void) { - ao_radio_pa_on(); - ao_exti_set_callback(AO_CC115L_INT_PORT, AO_CC115L_INT_PIN, ao_radio_isr); - ao_exti_enable(AO_CC115L_INT_PORT, AO_CC115L_INT_PIN); - ao_exti_enable(AO_CC115L_MCU_WAKEUP_PORT, AO_CC115L_MCU_WAKEUP_PIN); - ao_radio_strobe(CC115L_STX); } static void @@ -287,12 +307,9 @@ static const uint16_t packet_setup[] = { * * DATARATE_M = 67 * DATARATE_E = 6 - * - * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes */ #define RDF_DRATE_E 6 #define RDF_DRATE_M 67 -#define RDF_PACKET_LEN 50 static const uint16_t rdf_setup[] = { CC115L_DEVIATN, ((RDF_DEV_E << CC115L_DEVIATN_DEVIATION_E) | @@ -307,7 +324,7 @@ static const uint16_t rdf_setup[] = { */ #define APRS_DEV_E RDF_DEV_E -#define APRS_DEV_M RDF_DEV_E +#define APRS_DEV_M RDF_DEV_M /* * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate) @@ -342,21 +359,27 @@ static const uint16_t aprs_setup[] = { static uint16_t ao_radio_mode; + +/* + * These set the data rate and modulation parameters + */ #define AO_RADIO_MODE_BITS_PACKET_TX 1 -#define AO_RADIO_MODE_BITS_TX_BUF 2 -#define AO_RADIO_MODE_BITS_TX_FINISH 4 -#define AO_RADIO_MODE_BITS_RDF 8 -#define AO_RADIO_MODE_BITS_APRS 16 -#define AO_RADIO_MODE_BITS_INFINITE 32 -#define AO_RADIO_MODE_BITS_FIXED 64 +#define AO_RADIO_MODE_BITS_RDF 2 +#define AO_RADIO_MODE_BITS_APRS 4 + +/* + * Flips between infinite packet mode and fixed packet mode; + * we use infinite mode until the sender gives us the + * last chunk of data + */ +#define AO_RADIO_MODE_BITS_INFINITE 40 +#define AO_RADIO_MODE_BITS_FIXED 80 #define AO_RADIO_MODE_NONE 0 -#define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF) -#define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH) -#define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH) -#define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF) -#define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF) -#define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH) + +#define AO_RADIO_MODE_RDF AO_RADIO_MODE_BITS_RDF +#define AO_RADIO_MODE_PACKET_TX AO_RADIO_MODE_BITS_PACKET_TX +#define AO_RADIO_MODE_APRS AO_RADIO_MODE_BITS_APRS static void ao_radio_set_mode(uint16_t new_mode) @@ -372,12 +395,6 @@ ao_radio_set_mode(uint16_t new_mode) for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2) ao_radio_reg_write(packet_setup[i], packet_setup[i+1]); - if (changes & AO_RADIO_MODE_BITS_TX_BUF) - ao_radio_reg_write(AO_CC115L_INT_GPIO_IOCFG, CC115L_IOCFG_GPIO_CFG_TXFIFO_THR); - - if (changes & AO_RADIO_MODE_BITS_TX_FINISH) - ao_radio_reg_write(AO_CC115L_INT_GPIO_IOCFG, CC115L_IOCFG_GPIO_CFG_PKT_SYNC_TX | (1 << CC115L_IOCFG_GPIO_INV)); - if (changes & AO_RADIO_MODE_BITS_RDF) for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); @@ -395,8 +412,44 @@ ao_radio_set_mode(uint16_t new_mode) ao_radio_mode = new_mode; } +/*************************************************************** + * SmartRF Studio(tm) Export + * + * Radio register settings specifed with address, value + * + * RF device: CC115L + * + ***************************************************************/ + static const uint16_t radio_setup[] = { -#include "ao_rf_cc115l.h" + + /* High when FIFO is above threshold, low when fifo is below threshold */ + AO_CC115L_FIFO_INT_GPIO_IOCFG, CC115L_IOCFG_GPIO_CFG_TXFIFO_THR, + + /* High when transmitter is running, low when off */ + AO_CC115L_DONE_INT_GPIO_IOCFG, CC115L_IOCFG_GPIO_CFG_PA_PD | (1 << CC115L_IOCFG_GPIO_INV), + + CC115L_FIFOTHR, 0x47, /* TX FIFO Thresholds */ + CC115L_PKTCTRL0, 0x05, /* Packet Automation Control */ + CC115L_FREQ2, 0x10, /* Frequency Control Word, High Byte */ + CC115L_FREQ1, 0xb6, /* Frequency Control Word, Middle Byte */ + CC115L_FREQ0, 0xa5, /* Frequency Control Word, Low Byte */ + CC115L_MDMCFG4, 0xfa, /* Modem Configuration */ + CC115L_MDMCFG3, 0x83, /* Modem Configuration */ + CC115L_MDMCFG2, 0x13, /* Modem Configuration */ + CC115L_MDMCFG1, 0x21, /* Modem Configuration */ + CC115L_DEVIATN, 0x35, /* Modem Deviation Setting */ + CC115L_MCSM0, 0x18, /* Main Radio Control State Machine Configuration */ + CC115L_RESERVED_0X20, 0xfb, /* Use setting from SmartRF Studio */ + CC115L_FSCAL3, 0xe9, /* Frequency Synthesizer Calibration */ + CC115L_FSCAL2, 0x2a, /* Frequency Synthesizer Calibration */ + CC115L_FSCAL1, 0x00, /* Frequency Synthesizer Calibration */ + CC115L_FSCAL0, 0x1f, /* Frequency Synthesizer Calibration */ + CC115L_TEST2, 0x81, /* Various Test Settings */ + CC115L_TEST1, 0x35, /* Various Test Settings */ + CC115L_TEST0, 0x09, /* Various Test Settings */ + + CC115L_PA, 0x00, /* Power setting (0dBm) */ }; static uint8_t ao_radio_configured = 0; @@ -406,29 +459,11 @@ ao_radio_setup(void) { int i; -#if 0 - ao_gpio_set(AO_CC115L_SPI_CS_PORT, AO_CC115L_SPI_CS_PIN, AO_CC115L_SPI_CS, 0); - for (i = 0; i < 10000; i++) { - if (ao_gpio_get(SPI_2_PORT, SPI_2_MISO_PIN, SPI_2_MISO) == 0) { - printf ("Chip clock alive\n"); - break; - } - } - ao_gpio_set(AO_CC115L_SPI_CS_PORT, AO_CC115L_SPI_CS_PIN, AO_CC115L_SPI_CS, 1); - if (i == 10000) - printf ("Chip clock not alive\n"); -#endif - ao_radio_strobe(CC115L_SRES); ao_delay(AO_MS_TO_TICKS(10)); - printf ("Part %x\n", ao_radio_reg_read(CC115L_PARTNUM)); - printf ("Version %x\n", ao_radio_reg_read(CC115L_VERSION)); - - for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) { + for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); - ao_radio_reg_read(radio_setup[i]); - } ao_radio_mode = 0; @@ -449,7 +484,7 @@ ao_radio_set_len(uint8_t len) } static void -ao_radio_get(uint8_t len) +ao_radio_get(void) { static uint32_t last_radio_setting; static uint8_t last_power_setting; @@ -467,69 +502,100 @@ ao_radio_get(uint8_t len) ao_radio_reg_write(CC115L_PA, ao_config.radio_power); last_power_setting = ao_config.radio_power; } - ao_radio_set_len(len); } +static void +ao_radio_send_lots(ao_radio_fill_func fill, uint8_t mode); + #define ao_radio_put() ao_mutex_put(&ao_radio_mutex) -static void -ao_rdf_start(uint8_t len) +struct ao_radio_tone { + uint8_t value; + uint8_t len; +}; + +struct ao_radio_tone *ao_radio_tone; +uint8_t ao_radio_tone_count; +uint8_t ao_radio_tone_current; +uint8_t ao_radio_tone_offset; + +int16_t +ao_radio_tone_fill(uint8_t *buf, int16_t len) { - ao_radio_abort = 0; - ao_radio_get(len); + int16_t ret = 0; + + while (len) { + int16_t this_time; + struct ao_radio_tone *t; + + /* Figure out how many to send of the current value */ + t = &ao_radio_tone[ao_radio_tone_current]; + this_time = t->len - ao_radio_tone_offset; + if (this_time > len) + this_time = len; - ao_radio_set_mode(AO_RADIO_MODE_RDF); - ao_radio_wake = 0; + /* queue the data */ + memset(buf, t->value, this_time); + /* mark as sent */ + len -= this_time; + ao_radio_tone_offset += this_time; + ret += this_time; + + if (ao_radio_tone_offset >= t->len) { + ao_radio_tone_offset = 0; + ao_radio_tone_current++; + if (ao_radio_tone_current >= ao_radio_tone_count) { + trace_add(trace_line, __LINE__, ret, "done with tone"); + return -ret; + } + } + } + trace_add(trace_line, __LINE__, ret, "got some tone"); + return ret; } static void -ao_rdf_run(void) +ao_radio_tone_run(struct ao_radio_tone *tones, int ntones) { - ao_radio_start_tx(); - - ao_arch_block_interrupts(); - while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake) - ao_sleep(&ao_radio_wake); - ao_arch_release_interrupts(); - if (ao_radio_mcu_wake) - ao_radio_check_marcstate(); - ao_radio_pa_off(); - if (!ao_radio_wake) - ao_radio_idle(); - ao_radio_put(); + ao_radio_tone = tones; + ao_radio_tone_current = 0; + ao_radio_tone_offset = 0; + ao_radio_send_lots(ao_radio_tone_fill, AO_RADIO_MODE_RDF); } void ao_radio_rdf(void) { - ao_rdf_start(AO_RADIO_RDF_LEN); - - ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN); + struct ao_radio_tone tone; - ao_rdf_run(); + tone.value = ao_radio_rdf_value; + tone.len = AO_RADIO_RDF_LEN; + ao_radio_tone_run(&tone, 1); } void ao_radio_continuity(uint8_t c) { - uint8_t i; - uint8_t status; - - ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN); + struct ao_radio_tone tones[7]; + uint8_t count = 0; + uint8_t i; - status = ao_radio_fifo_write_start(); for (i = 0; i < 3; i++) { - ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); + tones[count].value = 0x00; + tones[count].len = AO_RADIO_CONT_PAUSE_LEN; + count++; if (i < c) - ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN); + tones[count].value = ao_radio_rdf_value; else - ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN); + tones[count].value = 0x00; + tones[count].len = AO_RADIO_CONT_TONE_LEN; + count++; } - ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); - status = ao_radio_fifo_write_stop(status); - (void) status; - ao_rdf_run(); + tones[count].value = 0x00; + tones[count].len = AO_RADIO_CONT_PAUSE_LEN; + count++; + ao_radio_tone_run(tones, count); } void @@ -557,17 +623,12 @@ ao_radio_test_cmd(void) #if PACKET_HAS_SLAVE ao_packet_slave_stop(); #endif - ao_radio_get(0xff); + ao_radio_get(); + ao_radio_set_len(0xff); + ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX | AO_RADIO_MODE_BITS_FIXED); + ao_radio_strobe(CC115L_SFTX); ao_radio_pa_on(); ao_radio_strobe(CC115L_STX); -#if CC115L_TRACE - { int t; - for (t = 0; t < 10; t++) { - printf ("status: %02x\n", ao_radio_status()); - ao_delay(AO_MS_TO_TICKS(100)); - } - } -#endif radio_on = 1; } if (mode == 3) { @@ -585,85 +646,76 @@ ao_radio_test_cmd(void) } } +static inline int16_t +ao_radio_gpio_bits(void) +{ + return AO_CC115L_DONE_INT_PORT->idr & ((1 << AO_CC115L_FIFO_INT_PIN) | + (1 << AO_CC115L_DONE_INT_PIN)); +} + static void -ao_radio_wait_isr(void) +ao_radio_wait_fifo(void) { ao_arch_block_interrupts(); - while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort) + while (!ao_radio_fifo && !ao_radio_done && !ao_radio_abort) { + trace_add(trace_line, __LINE__, ao_radio_gpio_bits(), "wait_fifo"); ao_sleep(&ao_radio_wake); + } ao_arch_release_interrupts(); - if (ao_radio_mcu_wake) - ao_radio_check_marcstate(); + trace_add(trace_line, __LINE__, ao_radio_gpio_bits(), "wake bits"); + trace_add(trace_line, __LINE__, ao_radio_fifo, "wake fifo"); + trace_add(trace_line, __LINE__, ao_radio_done, "wake done"); + trace_add(trace_line, __LINE__, ao_radio_abort, "wake abort"); } -static uint8_t -ao_radio_wait_tx(uint8_t wait_fifo) +static void +ao_radio_wait_done(void) { - uint8_t fifo_space = 0; - - do { - ao_radio_wait_isr(); - if (!wait_fifo) - return 0; - fifo_space = ao_radio_tx_fifo_space(); - } while (!fifo_space && !ao_radio_abort); - return fifo_space; + ao_arch_block_interrupts(); + while (!ao_radio_done && !ao_radio_abort) { + trace_add(trace_line, __LINE__, ao_radio_gpio_bits(), "wait_done"); + ao_sleep(&ao_radio_wake); + } + ao_arch_release_interrupts(); + trace_add(trace_line, __LINE__, ao_radio_gpio_bits(), "wake bits"); + trace_add(trace_line, __LINE__, ao_radio_fifo, "wake fifo"); + trace_add(trace_line, __LINE__, ao_radio_done, "wake done"); + trace_add(trace_line, __LINE__, ao_radio_abort, "wake abort"); } static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2]; -void -ao_radio_send(const void *d, uint8_t size) -{ - uint8_t marc_status; - uint8_t *e = tx_data; - uint8_t encode_len; - uint8_t this_len; - uint8_t started = 0; - uint8_t fifo_space; - - encode_len = ao_fec_encode(d, size, tx_data); +static uint8_t *ao_radio_send_buf; +static int16_t ao_radio_send_len; - ao_radio_get(encode_len); - - started = 0; - fifo_space = CC115L_FIFO_SIZE; - while (encode_len) { - this_len = encode_len; - - ao_radio_wake = 0; - if (this_len > fifo_space) { - this_len = fifo_space; - ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF); - } else { - ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH); - } +static int16_t +ao_radio_send_fill(uint8_t *buf, int16_t len) +{ + int16_t this_time; - ao_radio_fifo_write(e, this_len); - e += this_len; - encode_len -= this_len; + this_time = ao_radio_send_len; + if (this_time > len) + this_time = len; + memcpy(buf, ao_radio_send_buf, this_time); + ao_radio_send_buf += this_time; + ao_radio_send_len -= this_time; + if (ao_radio_send_len == 0) + return -this_time; + return this_time; +} - if (!started) { - ao_radio_start_tx(); - started = 1; - } else { - ao_exti_enable(AO_CC115L_INT_PORT, AO_CC115L_INT_PIN); - } - - fifo_space = ao_radio_wait_tx(encode_len != 0); - if (ao_radio_abort) { - ao_radio_idle(); - break; - } - } - ao_radio_pa_off(); - ao_radio_put(); +void +ao_radio_send(const void *d, uint8_t size) +{ + ao_radio_send_len = ao_fec_encode(d, size, tx_data); + ao_radio_send_buf = tx_data; + ao_radio_send_lots(ao_radio_send_fill, AO_RADIO_MODE_PACKET_TX); } #define AO_RADIO_LOTS 64 -void -ao_radio_send_lots(ao_radio_fill_func fill) +static void +ao_radio_send_lots(ao_radio_fill_func fill, uint8_t mode) { uint8_t buf[AO_RADIO_LOTS], *b; int cnt; @@ -672,10 +724,13 @@ ao_radio_send_lots(ao_radio_fill_func fill) uint8_t started = 0; uint8_t fifo_space; - ao_radio_get(0xff); + ao_radio_get(); fifo_space = CC115L_FIFO_SIZE; + ao_radio_done = 0; + ao_radio_fifo = 0; while (!done) { cnt = (*fill)(buf, sizeof(buf)); + trace_add(trace_line, __LINE__, cnt, "send data count"); if (cnt < 0) { done = 1; cnt = -cnt; @@ -683,8 +738,13 @@ ao_radio_send_lots(ao_radio_fill_func fill) total += cnt; /* At the last buffer, set the total length */ - if (done) + if (done) { ao_radio_set_len(total & 0xff); + ao_radio_set_mode(mode | AO_RADIO_MODE_BITS_FIXED); + } else { + ao_radio_set_len(0xff); + ao_radio_set_mode(mode | AO_RADIO_MODE_BITS_INFINITE); + } b = buf; while (cnt) { @@ -692,46 +752,49 @@ ao_radio_send_lots(ao_radio_fill_func fill) /* Wait for some space in the fifo */ while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) { - ao_radio_wake = 0; - ao_radio_wait_isr(); + trace_add(trace_line, __LINE__, this_len, "wait for space"); + ao_radio_wait_fifo(); } - if (ao_radio_abort) + if (ao_radio_abort || ao_radio_done) break; + trace_add(trace_line, __LINE__, fifo_space, "got space"); if (this_len > fifo_space) this_len = fifo_space; cnt -= this_len; - if (done) { - if (cnt) - ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF); - else - ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH); - } else - ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF); - + ao_radio_done = 0; + ao_radio_fifo = 0; ao_radio_fifo_write(b, this_len); b += this_len; + ao_exti_enable(AO_CC115L_FIFO_INT_PORT, AO_CC115L_FIFO_INT_PIN); + ao_exti_enable(AO_CC115L_DONE_INT_PORT, AO_CC115L_DONE_INT_PIN); + if (!started) { - ao_radio_start_tx(); + ao_radio_pa_on(); + ao_radio_strobe(CC115L_STX); started = 1; - } else - ao_exti_enable(AO_CC115L_INT_PORT, AO_CC115L_INT_PIN); + } } - if (ao_radio_abort) { - ao_radio_idle(); + if (ao_radio_abort || ao_radio_done) break; - } - /* Wait for the transmitter to go idle */ - ao_radio_wake = 0; - ao_radio_wait_isr(); } + if (ao_radio_abort) + ao_radio_idle(); + ao_radio_wait_done(); ao_radio_pa_off(); ao_radio_put(); } -static char *cc115l_state_name[] = { +void +ao_radio_send_aprs(ao_radio_fill_func fill) +{ + ao_radio_send_lots(fill, AO_RADIO_MODE_APRS); +} + +#if CC115L_DEBUG +const static char *cc115l_state_name[] = { [CC115L_STATUS_STATE_IDLE] = "IDLE", [CC115L_STATUS_STATE_TX] = "TX", [CC115L_STATUS_STATE_FSTXON] = "FSTXON", @@ -740,11 +803,6 @@ static char *cc115l_state_name[] = { [CC115L_STATUS_STATE_TX_FIFO_UNDERFLOW] = "TX_FIFO_UNDERFLOW", }; -struct ao_cc115l_reg { - uint16_t addr; - char *name; -}; - const static struct ao_cc115l_reg ao_cc115l_reg[] = { { .addr = CC115L_IOCFG2, .name = "IOCFG2" }, { .addr = CC115L_IOCFG1, .name = "IOCFG1" }, @@ -793,7 +851,7 @@ static void ao_radio_show(void) { uint8_t status = ao_radio_status(); int i; - ao_radio_get(0xff); + ao_radio_get(); status = ao_radio_status(); printf ("Status: %02x\n", status); printf ("CHIP_RDY: %d\n", (status >> CC115L_STATUS_CHIP_RDY) & 1); @@ -824,6 +882,8 @@ static void ao_radio_packet(void) { ao_radio_send(packet, sizeof (packet)); } +#endif /* CC115L_DEBUG */ + #if HAS_APRS #include @@ -869,17 +929,17 @@ ao_radio_init(void) ao_panic(AO_PANIC_SELF_TEST_CC115L); #endif - /* Enable the EXTI interrupt for the appropriate pin */ - ao_enable_port(AO_CC115L_INT_PORT); - ao_exti_setup(AO_CC115L_INT_PORT, AO_CC115L_INT_PIN, + /* Enable the fifo threhold interrupt pin */ + ao_enable_port(AO_CC115L_FIFO_INT_PORT); + ao_exti_setup(AO_CC115L_FIFO_INT_PORT, AO_CC115L_FIFO_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH, - ao_radio_isr); + ao_radio_fifo_isr); - /* Enable the hacked up GPIO3 pin */ - ao_enable_port(AO_CC115L_MCU_WAKEUP_PORT); - ao_exti_setup(AO_CC115L_MCU_WAKEUP_PORT, AO_CC115L_MCU_WAKEUP_PIN, + /* Enable the tx done interrupt pin */ + ao_enable_port(AO_CC115L_DONE_INT_PORT); + ao_exti_setup(AO_CC115L_DONE_INT_PORT, AO_CC115L_DONE_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, - ao_radio_mcu_wakeup_isr); + ao_radio_done_isr); ao_radio_pa_init(); diff --git a/src/drivers/ao_rf_cc115l.h b/src/drivers/ao_rf_cc115l.h deleted file mode 100644 index 50a730ab..00000000 --- a/src/drivers/ao_rf_cc115l.h +++ /dev/null @@ -1,83 +0,0 @@ -/*************************************************************** - * SmartRF Studio(tm) Export - * - * Radio register settings specifed with address, value - * - * RF device: CC115L - * - ***************************************************************/ - - -#if 0 - CC115L_IOCFG2, 0x2e, /* GDO2 Output Pin Configuration */ - CC115L_IOCFG1, 0x2e, /* GDO1 Output Pin Configuration */ - CC115L_IOCFG0, 0x06, /* GDO0 Output Pin Configuration */ - CC115L_FIFOTHR, 0x47, /* TX FIFO Thresholds */ - CC115L_SYNC1, 0xd3, /* Sync Word, High Byte */ - CC115L_SYNC0, 0x91, /* Sync Word, Low Byte */ - CC115L_PKTLEN, 0xff, /* Packet Length */ - CC115L_PKTCTRL0, 0x05, /* Packet Automation Control */ - CC115L_CHANNR, 0x00, /* Channel number */ - CC115L_FSCTRL0, 0x00, /* Frequency Synthesizer Control */ - CC115L_FREQ2, 0x10, /* Frequency Control Word, High Byte */ - CC115L_FREQ1, 0xb6, /* Frequency Control Word, Middle Byte */ - CC115L_FREQ0, 0xa5, /* Frequency Control Word, Low Byte */ - CC115L_MDMCFG4, 0xfa, /* Modem Configuration */ - CC115L_MDMCFG3, 0x83, /* Modem Configuration */ - CC115L_MDMCFG2, 0x13, /* Modem Configuration */ - CC115L_MDMCFG1, 0x21, /* Modem Configuration */ - CC115L_MDMCFG0, 0xf8, /* Modem Configuration */ - CC115L_DEVIATN, 0x35, /* Modem Deviation Setting */ - CC115L_MCSM1, 0x30, /* Main Radio Control State Machine Configuration */ - CC115L_MCSM0, 0x18, /* Main Radio Control State Machine Configuration */ - CC115L_RESERVED_0X20, 0xfb, /* Use setting from SmartRF Studio */ - CC115L_FREND0, 0x10, /* Front End TX Configuration */ - CC115L_FSCAL3, 0xe9, /* Frequency Synthesizer Calibration */ - CC115L_FSCAL2, 0x2a, /* Frequency Synthesizer Calibration */ - CC115L_FSCAL1, 0x00, /* Frequency Synthesizer Calibration */ - CC115L_FSCAL0, 0x1f, /* Frequency Synthesizer Calibration */ - CC115L_RESERVED_0X29, 0x89, /* Use setting from SmartRF Studio */ - CC115L_RESERVED_0X2A, 0x127, /* Use setting from SmartRF Studio */ - CC115L_RESERVED_0X2B, 0x63, /* Use setting from SmartRF Studio */ - CC115L_TEST2, 0x81, /* Various Test Settings */ - CC115L_TEST1, 0x35, /* Various Test Settings */ - CC115L_TEST0, 0x09, /* Various Test Settings */ - CC115L_PARTNUM, 0x00, /* Chip ID */ - CC115L_VERSION, 0x09, /* Chip ID */ - CC115L_MARCSTATE, 0x00, /* Main Radio Control State Machine State */ - CC115L_PKTSTATUS, 0x00, /* Current GDOx Status and Packet Status */ - CC115L_TXBYTES, 0x00, /* Underflow and Number of Bytes */ -#endif - -/*************************************************************** - * SmartRF Studio(tm) Export - * - * Radio register settings specifed with address, value - * - * RF device: CC115L - * - ***************************************************************/ - - - CC115L_IOCFG0, 0x06, /* GDO0 Output Pin Configuration */ - CC115L_FIFOTHR, 0x47, /* TX FIFO Thresholds */ - CC115L_PKTCTRL0, 0x05, /* Packet Automation Control */ - CC115L_FREQ2, 0x10, /* Frequency Control Word, High Byte */ - CC115L_FREQ1, 0xb6, /* Frequency Control Word, Middle Byte */ - CC115L_FREQ0, 0xa5, /* Frequency Control Word, Low Byte */ - CC115L_MDMCFG4, 0xfa, /* Modem Configuration */ - CC115L_MDMCFG3, 0x83, /* Modem Configuration */ - CC115L_MDMCFG2, 0x13, /* Modem Configuration */ - CC115L_MDMCFG1, 0x21, /* Modem Configuration */ - CC115L_DEVIATN, 0x35, /* Modem Deviation Setting */ - CC115L_MCSM0, 0x18, /* Main Radio Control State Machine Configuration */ - CC115L_RESERVED_0X20, 0xfb, /* Use setting from SmartRF Studio */ - CC115L_FSCAL3, 0xe9, /* Frequency Synthesizer Calibration */ - CC115L_FSCAL2, 0x2a, /* Frequency Synthesizer Calibration */ - CC115L_FSCAL1, 0x00, /* Frequency Synthesizer Calibration */ - CC115L_FSCAL0, 0x1f, /* Frequency Synthesizer Calibration */ - CC115L_TEST2, 0x81, /* Various Test Settings */ - CC115L_TEST1, 0x35, /* Various Test Settings */ - CC115L_TEST0, 0x09, /* Various Test Settings */ - - CC115L_PA, 0x00, /* Power setting (0dBm) */ diff --git a/src/telegps-v0.1/Makefile b/src/telegps-v0.1/Makefile index c8ab8a9a..ae36c9fd 100644 --- a/src/telegps-v0.1/Makefile +++ b/src/telegps-v0.1/Makefile @@ -14,7 +14,6 @@ INC = \ ao_task.h \ ao_whiten.h \ ao_cc115l.h \ - ao_rf_cc115l.h \ ao_fec.h \ stm32l.h \ Makefile diff --git a/src/telegps-v0.1/ao_pins.h b/src/telegps-v0.1/ao_pins.h index 09574568..eea050c9 100644 --- a/src/telegps-v0.1/ao_pins.h +++ b/src/telegps-v0.1/ao_pins.h @@ -140,17 +140,13 @@ #define AO_CC115L_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC115L_SPI stm_spi2 -#define AO_CC115L_INT_PORT (&stm_gpioa) -#define AO_CC115L_INT_PIN (9) +#define AO_CC115L_FIFO_INT_GPIO_IOCFG CC115L_IOCFG2 +#define AO_CC115L_FIFO_INT_PORT (&stm_gpioa) +#define AO_CC115L_FIFO_INT_PIN (9) -#define AO_CC115L_MCU_WAKEUP_PORT (&stm_gpioa) -#define AO_CC115L_MCU_WAKEUP_PIN (10) - -#define AO_CC115L_INT_GPIO 2 -#define AO_CC115L_INT_GPIO_IOCFG CC115L_IOCFG2 - -#define AO_CC115L_MARC_GPIO 0 -#define AO_CC115L_MARC_GPIO_IOCFG CC115L_IOCFG0 +#define AO_CC115L_DONE_INT_GPIO_IOCFG CC115L_IOCFG0 +#define AO_CC115L_DONE_INT_PORT (&stm_gpioa) +#define AO_CC115L_DONE_INT_PIN (10) #define HAS_RADIO_AMP 1 diff --git a/src/test/ao_aprs_test.c b/src/test/ao_aprs_test.c index 3b31f2d3..dd5eac4d 100644 --- a/src/test/ao_aprs_test.c +++ b/src/test/ao_aprs_test.c @@ -107,7 +107,7 @@ int main(int argc, char **argv) } void -ao_radio_send_lots(ao_radio_fill_func fill) +ao_radio_send_aprs(ao_radio_fill_func fill) { int16_t len; uint8_t done = 0; -- cgit v1.2.3 From 144b44e13ce3361ff59cbb555e84d542455a4e17 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 31 Mar 2013 12:39:32 -0700 Subject: altos: Unmount file system after each testing pass in ao_fat_test Otherwise, we use stale data and 'bad things' happen. Signed-off-by: Keith Packard --- src/drivers/ao_fat.c | 6 ++++++ src/drivers/ao_fat.h | 3 +++ src/test/ao_fat_test.c | 10 ++++++---- 3 files changed, 15 insertions(+), 4 deletions(-) (limited to 'src/test') diff --git a/src/drivers/ao_fat.c b/src/drivers/ao_fat.c index bb0aa7a2..9cd3d34b 100644 --- a/src/drivers/ao_fat.c +++ b/src/drivers/ao_fat.c @@ -608,6 +608,12 @@ ao_fat_setup(void) return ao_filesystem_status; } +void +ao_fat_unmount(void) +{ + ao_filesystem_setup = 0; +} + /* * Basic file operations */ diff --git a/src/drivers/ao_fat.h b/src/drivers/ao_fat.h index 40786990..36aec7df 100644 --- a/src/drivers/ao_fat.h +++ b/src/drivers/ao_fat.h @@ -63,6 +63,9 @@ ao_fat_init(void); void ao_fat_sync(void); +void +ao_fat_unmount(void); + int8_t ao_fat_full(void); diff --git a/src/test/ao_fat_test.c b/src/test/ao_fat_test.c index 48d5d8a4..eb55d9c8 100644 --- a/src/test/ao_fat_test.c +++ b/src/test/ao_fat_test.c @@ -226,14 +226,15 @@ fatal(char *msg, ...) void check_fat(void) { - int e; - int f; + cluster_t e; + int f; for (e = 0; e < number_cluster; e++) { cluster_t v = ao_fat_entry_raw_read(e, 0); for (f = 1; f < number_fat; f++) { - if (ao_fat_entry_raw_read(e, f) != v) - fatal ("fats differ at %d\n", e); + cluster_t o = ao_fat_entry_raw_read(e, f); + if (o != v) + fatal ("fats differ at %08x (0 %08x %d %08x)\n", e, v, f, o); } } } @@ -490,6 +491,7 @@ main(int argc, char **argv) #else long_test_fs(); #endif + ao_fat_unmount(); } return 0; -- cgit v1.2.3 From fae116fbebb9658fe15690ff43dfe8568a58c2a9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 1 Apr 2013 02:06:03 -0700 Subject: altos: Add a FAT test that re-writes the same file multiple times This caught a bunch of FAT cluster chain allocation bugs. Signed-off-by: Keith Packard --- src/test/ao_fat_test.c | 125 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 96 insertions(+), 29 deletions(-) (limited to 'src/test') diff --git a/src/test/ao_fat_test.c b/src/test/ao_fat_test.c index eb55d9c8..a1bd5fbf 100644 --- a/src/test/ao_fat_test.c +++ b/src/test/ao_fat_test.c @@ -350,28 +350,89 @@ uint32_t sizes[NUM_FILES]; unsigned char md5[NUM_FILES][MD5_DIGEST_LENGTH]; +void +micro_test_fs(void) +{ + int8_t fd; + char name[] = "FOO "; + char buf[512]; + int len; + + printf ("write once\n"); + if ((fd = ao_fat_creat(name)) >= 0) { + ao_fat_write(fd, "hello world\n", 12); + ao_fat_close(fd); + } + + printf ("read first\n"); + if ((fd = ao_fat_open(name, AO_FAT_OPEN_READ)) >= 0) { + len = ao_fat_read(fd, buf, sizeof(buf)); + write (1, buf, len); + ao_fat_close(fd); + } + + printf ("write again\n"); + if ((fd = ao_fat_creat(name)) >= 0) { + ao_fat_write(fd, "hi\n", 3); + ao_fat_close(fd); + } + + printf ("read again\n"); + if ((fd = ao_fat_open(name, AO_FAT_OPEN_READ)) >= 0) { + len = ao_fat_read(fd, buf, sizeof(buf)); + write (1, buf, len); + ao_fat_close(fd); + } + + printf ("write 3\n"); + if ((fd = ao_fat_creat(name)) >= 0) { + int l; + char c; + + for (l = 0; l < 10; l++) { + for (c = ' '; c < '~'; c++) + ao_fat_write(fd, &c, 1); + c = '\n'; + ao_fat_write(fd, &c, 1); + } + ao_fat_close(fd); + } + + printf ("read 3\n"); + if ((fd = ao_fat_open(name, AO_FAT_OPEN_READ)) >= 0) { + while ((len = ao_fat_read(fd, buf, sizeof(buf))) > 0) + write (1, buf, len); + ao_fat_close(fd); + } + + check_fs(); + printf ("all done\n"); +} + + void short_test_fs(void) { int len; + int8_t fd; char buf[345]; - if (ao_fat_open("HELLO TXT",AO_FAT_OPEN_READ) == AO_FAT_SUCCESS) { + if ((fd = ao_fat_open("HELLO TXT",AO_FAT_OPEN_READ)) >= 0) { printf ("File contents for HELLO.TXT\n"); - while ((len = ao_fat_read(buf, sizeof(buf)))) + while ((len = ao_fat_read(fd, buf, sizeof(buf)))) write(1, buf, len); - ao_fat_close(); + ao_fat_close(fd); } - if (ao_fat_creat("NEWFILE TXT") == AO_FAT_SUCCESS) { + if ((fd = ao_fat_creat("NEWFILE TXT")) >= 0) { printf ("Create new file\n"); for (len = 0; len < 2; len++) - ao_fat_write("hello, world!\n", 14); - ao_fat_seek(0, AO_FAT_SEEK_SET); + ao_fat_write(fd, "hello, world!\n", 14); + ao_fat_seek(fd, 0, AO_FAT_SEEK_SET); printf ("read new file\n"); - while ((len = ao_fat_read(buf, sizeof (buf)))) + while ((len = ao_fat_read(fd, buf, sizeof (buf)))) write (1, buf, len); - ao_fat_close(); + ao_fat_close(fd); } check_fs(); @@ -386,6 +447,7 @@ long_test_fs(void) unsigned char md5_check[MD5_DIGEST_LENGTH]; char buf[337]; int len; + int8_t fd; uint64_t total_file_size = 0; total_reads = total_writes = 0; @@ -395,10 +457,10 @@ long_test_fs(void) memset(sizes, '\0', sizeof (sizes)); for (id = 0; id < NUM_FILES; id++) { sprintf(name, "D%07dTXT", id); - if ((id % (NUM_FILES/50)) == 0) { + if ((id % ((NUM_FILES+49)/50)) == 0) { printf ("."); fflush(stdout); } - if (ao_fat_creat(name) == AO_FAT_SUCCESS) { + if ((fd = ao_fat_creat(name)) >= 0) { int j; char line[64]; check_bufio("file created"); @@ -407,7 +469,7 @@ long_test_fs(void) int len, ret; sprintf (line, "Hello, world %d %d\r\n", id, j); len = strlen(line); - ret = ao_fat_write((uint8_t *) line, len); + ret = ao_fat_write(fd, line, len); if (ret <= 0) break; total_file_size += ret; @@ -416,7 +478,7 @@ long_test_fs(void) if (ret != len) printf ("write failed %d\n", ret); } - ao_fat_close(); + ao_fat_close(fd); MD5_Final(&md5[id][0], &ctx); check_bufio("file written"); } @@ -436,16 +498,16 @@ long_test_fs(void) uint32_t size; sprintf(name, "D%07dTXT", id); size = 0; - if ((id % (NUM_FILES/50)) == 0) { + if ((id % ((NUM_FILES+49)/50)) == 0) { printf ("."); fflush(stdout); } - if (ao_fat_open(name, AO_FAT_OPEN_READ) == AO_FAT_SUCCESS) { + if ((fd = ao_fat_open(name, AO_FAT_OPEN_READ)) >= 0) { MD5_Init(&ctx); - while ((len = ao_fat_read((uint8_t *) buf, sizeof(buf))) > 0) { + while ((len = ao_fat_read(fd, buf, sizeof(buf))) > 0) { MD5_Update(&ctx, buf, len); size += len; } - ao_fat_close(); + ao_fat_close(fd); MD5_Final(md5_check, &ctx); if (size != sizes[id]) fatal("file %d: size differs %d written %d read\n", @@ -468,6 +530,20 @@ char *params[] = { NULL }; +void +do_test(void (*test)(void)) +{ + ao_fat_init(); + + check_bufio("top"); + ao_fat_setup(); + + check_fs(); + check_bufio("after setup"); + (*test)(); + ao_fat_unmount(); +} + int main(int argc, char **argv) { @@ -478,21 +554,12 @@ main(int argc, char **argv) for (p = 0; fs_params[p].fat; p++) { param = &fs_params[p]; - ao_fat_init(); - - check_bufio("top"); - ao_fat_setup(); - - check_fs(); - check_bufio("after setup"); -#ifdef SIMPLE_TEST - short_test_fs(); -#else - long_test_fs(); -#endif - ao_fat_unmount(); + do_test(micro_test_fs); + do_test(short_test_fs); + do_test(long_test_fs); } + unlink (fs); return 0; } -- cgit v1.2.3 From c54bd59780275ece87eafb8143cf0637b35e794c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Apr 2013 02:35:15 -0700 Subject: altos: Stick a mutex around FAT operations This allows the command line and logging operations to occur safely in parallel Signed-off-by: Keith Packard --- src/drivers/ao_fat.c | 436 ++++++++++++++++++++++++++++++------------------- src/test/ao_fat_test.c | 16 +- 2 files changed, 275 insertions(+), 177 deletions(-) (limited to 'src/test') diff --git a/src/drivers/ao_fat.c b/src/drivers/ao_fat.c index 87c4158b..afd645cd 100644 --- a/src/drivers/ao_fat.c +++ b/src/drivers/ao_fat.c @@ -50,6 +50,9 @@ typedef ao_fat_cluster_t cluster_t; typedef ao_fat_dirent_t dirent_t; typedef ao_fat_cluster_offset_t cluster_offset_t; +/* Global FAT lock */ +static uint8_t ao_fat_mutex; + /* Partition information, sector numbers */ static uint8_t partition_type; @@ -123,14 +126,14 @@ put_u16(uint8_t *base, uint16_t value) } static uint8_t -ao_fat_cluster_valid(cluster_t cluster) +_ao_fat_cluster_valid(cluster_t cluster) { return (2 <= cluster && cluster < number_cluster); } /* Start using a sector */ static uint8_t * -ao_fat_sector_get(sector_t sector) +_ao_fat_sector_get(sector_t sector) { sector += partition_start; if (sector >= partition_end) @@ -139,18 +142,18 @@ ao_fat_sector_get(sector_t sector) } /* Finish using a sector, 'w' is 1 if modified */ -#define ao_fat_sector_put(b,w) ao_bufio_put(b,w) +#define _ao_fat_sector_put(b,w) ao_bufio_put(b,w) /* Get the next cluster entry in the chain */ static cluster_t -ao_fat_entry_read(cluster_t cluster) +_ao_fat_entry_read(cluster_t cluster) { sector_t sector; cluster_t offset; uint8_t *buf; cluster_t ret; - if (!ao_fat_cluster_valid(cluster)) + if (!_ao_fat_cluster_valid(cluster)) return 0xfffffff7; if (fat32) @@ -159,7 +162,7 @@ ao_fat_entry_read(cluster_t cluster) cluster <<= 1; sector = cluster >> (SECTOR_SHIFT); offset = cluster & SECTOR_MASK; - buf = ao_fat_sector_get(fat_start + sector); + buf = _ao_fat_sector_get(fat_start + sector); if (!buf) return 0; @@ -171,7 +174,7 @@ ao_fat_entry_read(cluster_t cluster) if (AO_FAT_IS_LAST_CLUSTER16(ret)) ret |= 0xfff0000; } - ao_fat_sector_put(buf, 0); + _ao_fat_sector_put(buf, 0); return ret; } @@ -179,7 +182,7 @@ ao_fat_entry_read(cluster_t cluster) * 'new_value'. Return the previous value. */ static cluster_t -ao_fat_entry_replace(cluster_t cluster, cluster_t new_value) +_ao_fat_entry_replace(cluster_t cluster, cluster_t new_value) { sector_t sector; cluster_offset_t offset; @@ -188,7 +191,7 @@ ao_fat_entry_replace(cluster_t cluster, cluster_t new_value) cluster_t old_value; uint8_t fat; - if (!ao_fat_cluster_valid(cluster)) + if (!_ao_fat_cluster_valid(cluster)) return 0xfffffff7; /* Convert from cluster index to byte index */ @@ -201,7 +204,7 @@ ao_fat_entry_replace(cluster_t cluster, cluster_t new_value) new_value &= 0xfffffff; for (fat = 0; fat < number_fat; fat++) { - buf = ao_fat_sector_get(fat_start + fat * sectors_per_fat + sector); + buf = _ao_fat_sector_get(fat_start + fat * sectors_per_fat + sector); if (!buf) return 0; if (fat32) { @@ -231,7 +234,7 @@ ao_fat_entry_replace(cluster_t cluster, cluster_t new_value) } put_u16(buf + offset, new_value); } - ao_fat_sector_put(buf, 1); + _ao_fat_sector_put(buf, 1); } return ret; @@ -242,19 +245,19 @@ ao_fat_entry_replace(cluster_t cluster, cluster_t new_value) * all of them as free */ static void -ao_fat_free_cluster_chain(cluster_t cluster) +_ao_fat_free_cluster_chain(cluster_t cluster) { - while (ao_fat_cluster_valid(cluster)) { + while (_ao_fat_cluster_valid(cluster)) { if (cluster < next_free) { next_free = cluster; fsinfo_dirty = 1; } - cluster = ao_fat_entry_replace(cluster, 0x00000000); + cluster = _ao_fat_entry_replace(cluster, 0x00000000); } } /* - * ao_fat_cluster_seek + * _ao_fat_cluster_seek * * The basic file system operation -- map a file cluster index to a * partition cluster number. Done by computing the cluster number and @@ -263,11 +266,11 @@ ao_fat_free_cluster_chain(cluster_t cluster) * is damaged somehow */ static cluster_t -ao_fat_cluster_seek(cluster_t cluster, cluster_t distance) +_ao_fat_cluster_seek(cluster_t cluster, cluster_t distance) { while (distance) { - cluster = ao_fat_entry_read(cluster); - if (!ao_fat_cluster_valid(cluster)) + cluster = _ao_fat_entry_read(cluster); + if (!_ao_fat_cluster_valid(cluster)) break; distance--; } @@ -275,7 +278,7 @@ ao_fat_cluster_seek(cluster_t cluster, cluster_t distance) } /* - * ao_fat_cluster_set_size + * _ao_fat_cluster_set_size * * Set the number of clusters in the specified chain, * freeing extra ones or alocating new ones as needed @@ -284,7 +287,7 @@ ao_fat_cluster_seek(cluster_t cluster, cluster_t distance) */ static cluster_t -ao_fat_cluster_set_size(cluster_t first_cluster, cluster_t size) +_ao_fat_cluster_set_size(cluster_t first_cluster, cluster_t size) { cluster_t have; cluster_t last_cluster; @@ -300,10 +303,10 @@ ao_fat_cluster_set_size(cluster_t first_cluster, cluster_t size) DBG("\tclusters:"); for (have = 0; have < size; have++) { DBG(" %08x", next_cluster); - if (!ao_fat_cluster_valid(next_cluster)) + if (!_ao_fat_cluster_valid(next_cluster)) break; last_cluster = next_cluster; - next_cluster = ao_fat_entry_read(next_cluster); + next_cluster = _ao_fat_entry_read(next_cluster); } DBG("\n"); @@ -320,14 +323,14 @@ ao_fat_cluster_set_size(cluster_t first_cluster, cluster_t size) */ if (have == size) { /* The file is large enough, truncate as needed */ - if (ao_fat_cluster_valid(next_cluster)) { + if (_ao_fat_cluster_valid(next_cluster)) { DBG("truncate between %08x and %08x\n", last_cluster, next_cluster); if (last_cluster) /* * Otherwise, rewrite the last cluster * in the chain with a LAST marker */ - (void) ao_fat_entry_replace(last_cluster, + (void) _ao_fat_entry_replace(last_cluster, AO_FAT_LAST_CLUSTER); else /* @@ -338,7 +341,7 @@ ao_fat_cluster_set_size(cluster_t first_cluster, cluster_t size) first_cluster = 0; /* Clear the remaining clusters in the chain */ - ao_fat_free_cluster_chain(next_cluster); + _ao_fat_free_cluster_chain(next_cluster); /* The file system is no longer full (if it was) */ filesystem_full = 0; @@ -371,7 +374,7 @@ ao_fat_cluster_set_size(cluster_t first_cluster, cluster_t size) break; \ loop_cluster { - if (!ao_fat_entry_read(free)) + if (!_ao_fat_entry_read(free)) need--; next_cluster; } @@ -387,14 +390,14 @@ ao_fat_cluster_set_size(cluster_t first_cluster, cluster_t size) */ need = size - have; loop_cluster { - if (ao_fat_entry_read(free) == 0) { + if (_ao_fat_entry_read(free) == 0) { next_free = free + 1; if (next_free >= number_cluster) next_free = 2; fsinfo_dirty = 1; DBG("\tadd cluster. old %08x new %08x\n", last_cluster, free); if (last_cluster) - ao_fat_entry_replace(last_cluster, free); + _ao_fat_entry_replace(last_cluster, free); else first_cluster = free; last_cluster = free; @@ -406,7 +409,7 @@ ao_fat_cluster_set_size(cluster_t first_cluster, cluster_t size) #undef next_cluster DBG("\tlast cluster %08x\n", last_cluster); /* Mark the new end of the chain */ - ao_fat_entry_replace(last_cluster, AO_FAT_LAST_CLUSTER); + _ao_fat_entry_replace(last_cluster, AO_FAT_LAST_CLUSTER); } DBG("\tfirst cluster %08x\n", first_cluster); @@ -415,7 +418,7 @@ ao_fat_cluster_set_size(cluster_t first_cluster, cluster_t size) /* Start using a root directory entry */ static uint8_t * -ao_fat_root_get(dirent_t e) +_ao_fat_root_get(dirent_t e) { offset_t byte = e * DIRENT_SIZE; sector_t sector = byte >> SECTOR_SHIFT; @@ -425,9 +428,9 @@ ao_fat_root_get(dirent_t e) if (fat32) { cluster_t cluster_distance = sector / sectors_per_cluster; sector_t sector_index = sector % sectors_per_cluster; - cluster_t cluster = ao_fat_cluster_seek(root_cluster, cluster_distance); + cluster_t cluster = _ao_fat_cluster_seek(root_cluster, cluster_distance); - if (ao_fat_cluster_valid(cluster)) + if (_ao_fat_cluster_valid(cluster)) sector = data_start + (cluster-2) * sectors_per_cluster + sector_index; else return NULL; @@ -437,7 +440,7 @@ ao_fat_root_get(dirent_t e) sector = root_start + sector; } - buf = ao_fat_sector_get(sector); + buf = _ao_fat_sector_get(sector); if (!buf) return NULL; return buf + offset; @@ -445,21 +448,21 @@ ao_fat_root_get(dirent_t e) /* Finish using a root directory entry, 'w' is 1 if modified */ static void -ao_fat_root_put(uint8_t *root, dirent_t e, uint8_t write) +_ao_fat_root_put(uint8_t *root, dirent_t e, uint8_t write) { cluster_offset_t offset = ((e * DIRENT_SIZE) & SECTOR_MASK); uint8_t *buf = root - offset; - ao_fat_sector_put(buf, write); + _ao_fat_sector_put(buf, write); } /* - * ao_fat_root_extend + * _ao_fat_root_extend * * On FAT32, make the root directory at least 'ents' entries long */ static int8_t -ao_fat_root_extend(dirent_t ents) +_ao_fat_root_extend(dirent_t ents) { offset_t byte_size; cluster_t cluster_size; @@ -468,18 +471,18 @@ ao_fat_root_extend(dirent_t ents) byte_size = (ents + 1) * 0x20; cluster_size = (byte_size + bytes_per_cluster - 1) / bytes_per_cluster; - if (ao_fat_cluster_set_size(root_cluster, cluster_size) != AO_FAT_BAD_CLUSTER) + if (_ao_fat_cluster_set_size(root_cluster, cluster_size) != AO_FAT_BAD_CLUSTER) return 1; return 0; } /* - * ao_fat_setup_partition + * _ao_fat_setup_partition * * Load the boot block and find the first partition */ static uint8_t -ao_fat_setup_partition(void) +_ao_fat_setup_partition(void) { uint8_t *mbr; uint8_t *partition; @@ -538,9 +541,9 @@ ao_fat_setup_partition(void) } static uint8_t -ao_fat_setup_fs(void) +_ao_fat_setup_fs(void) { - uint8_t *boot = ao_fat_sector_get(0); + uint8_t *boot = _ao_fat_sector_get(0); uint32_t data_sectors; if (!boot) @@ -550,7 +553,7 @@ ao_fat_setup_fs(void) if (boot[0x1fe] != 0x55 || boot[0x1ff] != 0xaa) { DBG ("Invalid BOOT signature %02x %02x\n", boot[0x1fe], boot[0x1ff]); - ao_fat_sector_put(boot, 0); + _ao_fat_sector_put(boot, 0); return AO_FAT_FILESYSTEM_INVALID_BOOT_SIGNATURE; } @@ -558,7 +561,7 @@ ao_fat_setup_fs(void) if (get_u16(boot + 0xb) != SECTOR_SIZE) { DBG ("Invalid sector size %d\n", get_u16(boot + 0xb)); - ao_fat_sector_put(boot, 0); + _ao_fat_sector_put(boot, 0); return AO_FAT_FILESYSTEM_INVALID_SECTOR_SIZE; } @@ -575,17 +578,17 @@ ao_fat_setup_fs(void) root_cluster = get_u32(boot+0x2c); fsinfo_sector = get_u16(boot + 0x30); } - ao_fat_sector_put(boot, 0); + _ao_fat_sector_put(boot, 0); free_count = 0xffffffff; next_free = 0; if (fat32 && fsinfo_sector) { - uint8_t *fsinfo = ao_fat_sector_get(fsinfo_sector); + uint8_t *fsinfo = _ao_fat_sector_get(fsinfo_sector); if (fsinfo) { free_count = get_u32(fsinfo + 0x1e8); next_free = get_u32(fsinfo + 0x1ec); - ao_fat_sector_put(fsinfo, 0); + _ao_fat_sector_put(fsinfo, 0); } } @@ -617,7 +620,7 @@ struct ao_file { static struct ao_fat_dirent ao_file_dirent[AO_FAT_NFILE]; static struct ao_fat_dirent * -ao_fat_file_dirent_alloc(struct ao_fat_dirent *want) +_ao_fat_file_dirent_alloc(struct ao_fat_dirent *want) { int8_t d; struct ao_fat_dirent *free = NULL, *dirent; @@ -645,13 +648,13 @@ ao_fat_file_dirent_alloc(struct ao_fat_dirent *want) static struct ao_file ao_file_table[AO_FAT_NFILE]; static int8_t -ao_fat_fd_alloc(struct ao_fat_dirent *dirent) +_ao_fat_fd_alloc(struct ao_fat_dirent *dirent) { int8_t fd; for (fd = 0; fd < AO_FAT_NFILE; fd++) if (!ao_file_table[fd].busy) { - ao_file_table[fd].dirent = ao_fat_file_dirent_alloc(dirent); + ao_file_table[fd].dirent = _ao_fat_file_dirent_alloc(dirent); ao_file_table[fd].busy = 1; ao_file_table[fd].offset = 0; ao_file_table[fd].cluster_offset = 0; @@ -663,7 +666,7 @@ ao_fat_fd_alloc(struct ao_fat_dirent *dirent) } static void -ao_fat_fd_free(int8_t fd) +_ao_fat_fd_free(int8_t fd) { struct ao_file *file = &ao_file_table[fd]; struct ao_fat_dirent *dirent = file->dirent; @@ -677,7 +680,7 @@ ao_fat_fd_free(int8_t fd) } static struct ao_file * -ao_fat_fd_to_file(int8_t fd) +_ao_fat_fd_to_file(int8_t fd) { struct ao_file *file; if (fd < 0 || AO_FAT_NFILE <= fd) @@ -693,7 +696,7 @@ static uint8_t ao_filesystem_setup; static uint8_t ao_filesystem_status; static uint8_t -ao_fat_setup(void) +_ao_fat_setup(void) { if (!ao_filesystem_setup) { @@ -713,10 +716,10 @@ ao_fat_setup(void) /* Reset open file table */ memset(&ao_file_table, '\0', sizeof (ao_file_table)); - ao_filesystem_status = ao_fat_setup_partition(); + ao_filesystem_status = _ao_fat_setup_partition(); if (ao_filesystem_status != AO_FAT_FILESYSTEM_SUCCESS) return ao_filesystem_status; - ao_filesystem_status = ao_fat_setup_fs(); + ao_filesystem_status = _ao_fat_setup_fs(); if (ao_filesystem_status != AO_FAT_FILESYSTEM_SUCCESS) return ao_filesystem_status; } @@ -734,7 +737,7 @@ ao_fat_unmount(void) */ static uint32_t -ao_fat_current_sector(struct ao_file *file) +_ao_fat_current_sector(struct ao_file *file) { cluster_t cluster_offset; uint32_t sector_offset; @@ -766,9 +769,9 @@ ao_fat_current_sector(struct ao_file *file) cluster_distance = cluster_offset - file->cluster_offset / bytes_per_cluster; DBG("\tseek forward %d clusters\n", cluster_distance); - cluster = ao_fat_cluster_seek(file->cluster, cluster_distance); + cluster = _ao_fat_cluster_seek(file->cluster, cluster_distance); - if (!ao_fat_cluster_valid(cluster)) { + if (!_ao_fat_cluster_valid(cluster)) { printf ("invalid cluster %08x\n", cluster); return 0xffffffff; } @@ -784,14 +787,14 @@ ao_fat_current_sector(struct ao_file *file) } /* - * ao_fat_invaldate_cluster_offset + * _ao_fat_invaldate_cluster_offset * * When the file size gets shrunk, invalidate * any file structures referencing clusters beyond that point */ static void -ao_fat_invalidate_cluster_offset(struct ao_fat_dirent *dirent) +_ao_fat_invalidate_cluster_offset(struct ao_fat_dirent *dirent) { int8_t fd; struct ao_file *file; @@ -811,13 +814,13 @@ ao_fat_invalidate_cluster_offset(struct ao_fat_dirent *dirent) /* - * ao_fat_set_size + * _ao_fat_set_size * * Set the size of the current file, truncating or extending * the cluster chain as needed */ static int8_t -ao_fat_set_size(struct ao_file *file, uint32_t size) +_ao_fat_set_size(struct ao_file *file, uint32_t size) { uint8_t *dent; cluster_t first_cluster; @@ -844,12 +847,12 @@ ao_fat_set_size(struct ao_file *file, uint32_t size) offset_clusters, extra_clusters); /* Need one more to account for file->cluster, which we already have */ - next_cluster = ao_fat_cluster_set_size(file->cluster, extra_clusters + 1); + next_cluster = _ao_fat_cluster_set_size(file->cluster, extra_clusters + 1); if (next_cluster == AO_FAT_BAD_CLUSTER) return -AO_FAT_ENOSPC; } else { DBG ("\tset size absolute need_clusters %d\n", need_clusters); - first_cluster = ao_fat_cluster_set_size(first_cluster, need_clusters); + first_cluster = _ao_fat_cluster_set_size(first_cluster, need_clusters); if (first_cluster == AO_FAT_BAD_CLUSTER) return -AO_FAT_ENOSPC; @@ -858,7 +861,7 @@ ao_fat_set_size(struct ao_file *file, uint32_t size) DBG ("\tupdate directory size\n"); /* Update the directory entry */ - dent = ao_fat_root_get(file->dirent->entry); + dent = _ao_fat_root_get(file->dirent->entry); if (!dent) { printf ("dent update failed\n"); return -AO_FAT_EIO; @@ -867,23 +870,23 @@ ao_fat_set_size(struct ao_file *file, uint32_t size) put_u16(dent + 0x1a, first_cluster); if (fat32) put_u16(dent + 0x14, first_cluster >> 16); - ao_fat_root_put(dent, file->dirent->entry, 1); + _ao_fat_root_put(dent, file->dirent->entry, 1); file->dirent->size = size; file->dirent->cluster = first_cluster; if (have_clusters > need_clusters) - ao_fat_invalidate_cluster_offset(file->dirent); + _ao_fat_invalidate_cluster_offset(file->dirent); DBG ("set size done\n"); return AO_FAT_SUCCESS; } /* - * ao_fat_root_init + * _ao_fat_root_init * * Initialize a root directory entry */ static void -ao_fat_root_init(uint8_t *dent, char name[11], uint8_t attr) +_ao_fat_root_init(uint8_t *dent, char name[11], uint8_t attr) { memset(dent, '\0', 0x20); memmove(dent, name, 11); @@ -916,7 +919,7 @@ ao_fat_root_init(uint8_t *dent, char name[11], uint8_t attr) static void -ao_fat_dirent_init(struct ao_fat_dirent *dirent, uint8_t *dent, uint16_t entry) +_ao_fat_dirent_init(struct ao_fat_dirent *dirent, uint8_t *dent, uint16_t entry) { memcpy(dirent->name, dent + 0x00, 11); dirent->attr = dent[0x0b]; @@ -928,13 +931,13 @@ ao_fat_dirent_init(struct ao_fat_dirent *dirent, uint8_t *dent, uint16_t entry) } /* - * ao_fat_flush_fsinfo + * _ao_fat_flush_fsinfo * * Write out any fsinfo changes to disk */ static void -ao_fat_flush_fsinfo(void) +_ao_fat_flush_fsinfo(void) { uint8_t *fsinfo; @@ -947,11 +950,11 @@ ao_fat_flush_fsinfo(void) if (!fsinfo_sector) return; - fsinfo = ao_fat_sector_get(fsinfo_sector); + fsinfo = _ao_fat_sector_get(fsinfo_sector); if (fsinfo) { put_u32(fsinfo + 0x1e8, free_count); put_u32(fsinfo + 0x1ec, next_free); - ao_fat_sector_put(fsinfo, 1); + _ao_fat_sector_put(fsinfo, 1); } } @@ -965,15 +968,23 @@ ao_fat_flush_fsinfo(void) * Flush any pending I/O to storage */ -void -ao_fat_sync(void) +static void +_ao_fat_sync(void) { - if (ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS) + if (_ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS) return; - ao_fat_flush_fsinfo(); + _ao_fat_flush_fsinfo(); ao_bufio_flush(); } +void +ao_fat_sync(void) +{ + ao_mutex_get(&ao_fat_mutex); + _ao_fat_sync(); + ao_mutex_put(&ao_fat_mutex); +} + /* * ao_fat_full * @@ -984,28 +995,71 @@ ao_fat_sync(void) int8_t ao_fat_full(void) { - if (ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS) + ao_mutex_get(&ao_fat_mutex); + if (_ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS) { + ao_mutex_put(&ao_fat_mutex); return 1; + } + ao_mutex_put(&ao_fat_mutex); return filesystem_full; } +static int8_t +_ao_fat_readdir(uint16_t *entry, struct ao_fat_dirent *dirent) +{ + uint8_t *dent; + + if (_ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS) + return -AO_FAT_EIO; + + for (;;) { + dent = _ao_fat_root_get(*entry); + if (!dent) + return -AO_FAT_EDIREOF; + + if (dent[0] == AO_FAT_DENT_END) { + _ao_fat_root_put(dent, *entry, 0); + return -AO_FAT_EDIREOF; + } + if (dent[0] != AO_FAT_DENT_EMPTY && (dent[0xb] & 0xf) != 0xf) { + _ao_fat_dirent_init(dirent, dent, *entry); + _ao_fat_root_put(dent, *entry, 0); + (*entry)++; + return AO_FAT_SUCCESS; + } + _ao_fat_root_put(dent, *entry, 0); + (*entry)++; + } +} + +int8_t +ao_fat_readdir(uint16_t *entry, struct ao_fat_dirent *dirent) +{ + int8_t status; + + ao_mutex_get(&ao_fat_mutex); + status = _ao_fat_readdir(entry, dirent); + ao_mutex_put(&ao_fat_mutex); + return status; +} + /* * ao_fat_open * * Open an existing file. */ -int8_t -ao_fat_open(char name[11], uint8_t mode) +static int8_t +_ao_fat_open(char name[11], uint8_t mode) { uint16_t entry = 0; struct ao_fat_dirent dirent; int8_t status; - if (ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS) + if (_ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS) return -AO_FAT_EIO; for (;;) { - status = ao_fat_readdir(&entry, &dirent); + status = _ao_fat_readdir(&entry, &dirent); if (status < 0) { if (status == -AO_FAT_EDIREOF) return -AO_FAT_ENOENT; @@ -1018,20 +1072,62 @@ ao_fat_open(char name[11], uint8_t mode) return -AO_FAT_EPERM; if (mode > AO_FAT_OPEN_READ && (dirent.attr & AO_FAT_FILE_READ_ONLY)) return -AO_FAT_EACCESS; - return ao_fat_fd_alloc(&dirent); + return _ao_fat_fd_alloc(&dirent); } } return -AO_FAT_ENOENT; } +int8_t +ao_fat_open(char name[11], uint8_t mode) +{ + int8_t status; + + ao_mutex_get(&ao_fat_mutex); + status = _ao_fat_open(name, mode); + ao_mutex_put(&ao_fat_mutex); + return status; +} + +/* + * ao_fat_close + * + * Close the currently open file + */ +static int8_t +_ao_fat_close(int8_t fd) +{ + struct ao_file *file; + + file = _ao_fat_fd_to_file(fd); + if (!file) + return -AO_FAT_EBADF; + + _ao_fat_fd_free(fd); + _ao_fat_sync(); + return AO_FAT_SUCCESS; +} + +int8_t +ao_fat_close(int8_t fd) +{ + int8_t status; + + ao_mutex_get(&ao_fat_mutex); + status = _ao_fat_close(fd); + ao_mutex_put(&ao_fat_mutex); + return status; +} + /* * ao_fat_creat * * Open and truncate an existing file or * create a new file */ -int8_t -ao_fat_creat(char name[11]) + +static int8_t +_ao_fat_creat(char name[11]) { uint16_t entry; int8_t fd; @@ -1039,50 +1135,50 @@ ao_fat_creat(char name[11]) uint8_t *dent; struct ao_file *file; - if (ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS) + if (_ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS) return -AO_FAT_EIO; - fd = ao_fat_open(name, AO_FAT_OPEN_WRITE); + fd = _ao_fat_open(name, AO_FAT_OPEN_WRITE); if (fd >= 0) { file = &ao_file_table[fd]; - status = ao_fat_set_size(file, 0); + status = _ao_fat_set_size(file, 0); if (status < 0) { - ao_fat_close(fd); + _ao_fat_close(fd); fd = status; } } else { if (fd == -AO_FAT_ENOENT) { entry = 0; for (;;) { - dent = ao_fat_root_get(entry); + dent = _ao_fat_root_get(entry); if (!dent) { - if (ao_fat_root_extend(entry)) + if (_ao_fat_root_extend(entry)) continue; fd = -AO_FAT_ENOSPC; break; } if (dent[0] == AO_FAT_DENT_EMPTY || dent[0] == AO_FAT_DENT_END) { - fd = ao_fat_fd_alloc(NULL); + fd = _ao_fat_fd_alloc(NULL); if (fd < 0) { - ao_fat_root_put(dent, entry, 0); + _ao_fat_root_put(dent, entry, 0); break; } file = &ao_file_table[fd]; /* Initialize the dent */ - ao_fat_root_init(dent, name, AO_FAT_FILE_REGULAR); + _ao_fat_root_init(dent, name, AO_FAT_FILE_REGULAR); /* Now initialize the dirent from the dent */ - ao_fat_dirent_init(file->dirent, dent, entry); + _ao_fat_dirent_init(file->dirent, dent, entry); /* And write the dent to storage */ - ao_fat_root_put(dent, entry, 1); + _ao_fat_root_put(dent, entry, 1); status = -AO_FAT_SUCCESS; break; } else { - ao_fat_root_put(dent, entry, 0); + _ao_fat_root_put(dent, entry, 0); } entry++; } @@ -1091,21 +1187,15 @@ ao_fat_creat(char name[11]) return fd; } -/* - * ao_fat_close - * - * Close the currently open file - */ int8_t -ao_fat_close(int8_t fd) +ao_fat_creat(char name[11]) { - struct ao_file *file = ao_fat_fd_to_file(fd); - if (!file) - return -AO_FAT_EBADF; + int8_t status; - ao_fat_fd_free(fd); - ao_fat_sync(); - return AO_FAT_SUCCESS; + ao_mutex_get(&ao_fat_mutex); + status = _ao_fat_creat(name); + ao_mutex_put(&ao_fat_mutex); + return status; } /* @@ -1122,12 +1212,12 @@ ao_fat_map_current(struct ao_file *file, int len, cluster_offset_t *offsetp, clu void *buf; offset = file->offset & SECTOR_MASK; - sector = ao_fat_current_sector(file); + sector = _ao_fat_current_sector(file); if (sector == 0xffffffff) { printf ("invalid sector at offset %d\n", file->offset); return NULL; } - buf = ao_fat_sector_get(sector); + buf = _ao_fat_sector_get(sector); if (!buf) printf ("sector get failed. Sector %d. Partition end %d\n", sector, partition_end); if (offset + len < SECTOR_SIZE) @@ -1151,9 +1241,14 @@ ao_fat_read(int8_t fd, void *dst, int len) cluster_offset_t offset; uint8_t *buf; int ret = 0; - struct ao_file *file = ao_fat_fd_to_file(fd); - if (!file) - return -AO_FAT_EBADF; + struct ao_file *file; + + ao_mutex_get(&ao_fat_mutex); + file = _ao_fat_fd_to_file(fd); + if (!file) { + ret = -AO_FAT_EBADF; + goto done; + } if (file->offset + len > file->dirent->size) len = file->dirent->size - file->offset; @@ -1169,13 +1264,15 @@ ao_fat_read(int8_t fd, void *dst, int len) break; } memcpy(dst_b, buf + offset, this_time); - ao_fat_sector_put(buf, 0); + _ao_fat_sector_put(buf, 0); ret += this_time; len -= this_time; dst_b += this_time; file->offset = file->offset + this_time; } +done: + ao_mutex_put(&ao_fat_mutex); return ret; } @@ -1192,14 +1289,19 @@ ao_fat_write(int8_t fd, void *src, int len) cluster_offset_t offset; uint8_t *buf; int ret = 0; - struct ao_file *file = ao_fat_fd_to_file(fd); - if (!file) - return -AO_FAT_EBADF; + struct ao_file *file; + + ao_mutex_get(&ao_fat_mutex); + file = _ao_fat_fd_to_file(fd); + if (!file) { + ret = -AO_FAT_EBADF; + goto done; + } if (file->offset + len > file->dirent->size) { - ret = ao_fat_set_size(file, file->offset + len); + ret = _ao_fat_set_size(file, file->offset + len); if (ret < 0) - return ret; + goto done; } while (len) { @@ -1210,13 +1312,15 @@ ao_fat_write(int8_t fd, void *src, int len) break; } memcpy(buf + offset, src_b, this_time); - ao_fat_sector_put(buf, 1); + _ao_fat_sector_put(buf, 1); ret += this_time; len -= this_time; src_b += this_time; file->offset = file->offset + this_time; } +done: + ao_mutex_put(&ao_fat_mutex); return ret; } @@ -1233,9 +1337,15 @@ int32_t ao_fat_seek(int8_t fd, int32_t pos, uint8_t whence) { offset_t new_offset; - struct ao_file *file = ao_fat_fd_to_file(fd); - if (!file) - return -AO_FAT_EBADF; + struct ao_file *file; + int32_t ret; + + ao_mutex_get(&ao_fat_mutex); + file = _ao_fat_fd_to_file(fd); + if (!file) { + ret = -AO_FAT_EBADF; + goto done; + } new_offset = file->offset; switch (whence) { @@ -1249,8 +1359,10 @@ ao_fat_seek(int8_t fd, int32_t pos, uint8_t whence) new_offset = file->dirent->size + pos; break; } - file->offset = new_offset; - return file->offset; + ret = file->offset = new_offset; +done: + ao_mutex_put(&ao_fat_mutex); + return ret; } /* @@ -1264,9 +1376,13 @@ ao_fat_unlink(char name[11]) { uint16_t entry = 0; struct ao_fat_dirent dirent; + int8_t ret; - if (ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS) - return -AO_FAT_EIO; + ao_mutex_get(&ao_fat_mutex); + if (_ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS) { + ret = -AO_FAT_EIO; + goto done; + } while (ao_fat_readdir(&entry, &dirent)) { if (memcmp(name, dirent.name, 11) == 0) { @@ -1274,30 +1390,38 @@ ao_fat_unlink(char name[11]) uint8_t *ent; uint8_t delete; - if (AO_FAT_IS_DIR(dirent.attr)) - return -AO_FAT_EISDIR; - if (!AO_FAT_IS_FILE(dirent.attr)) - return -AO_FAT_EPERM; + if (AO_FAT_IS_DIR(dirent.attr)) { + ret = -AO_FAT_EISDIR; + goto done; + } + if (!AO_FAT_IS_FILE(dirent.attr)) { + ret = -AO_FAT_EPERM; + goto done; + } - ao_fat_free_cluster_chain(dirent.cluster); - next = ao_fat_root_get(dirent.entry + 1); + _ao_fat_free_cluster_chain(dirent.cluster); + next = _ao_fat_root_get(dirent.entry + 1); if (next && next[0] != AO_FAT_DENT_END) delete = AO_FAT_DENT_EMPTY; else delete = AO_FAT_DENT_END; if (next) - ao_fat_root_put(next, dirent.entry + 1, 0); - ent = ao_fat_root_get(dirent.entry); + _ao_fat_root_put(next, dirent.entry + 1, 0); + ent = _ao_fat_root_get(dirent.entry); if (ent) { memset(ent, '\0', DIRENT_SIZE); *ent = delete; - ao_fat_root_put(ent, dirent.entry, 1); + _ao_fat_root_put(ent, dirent.entry, 1); } ao_bufio_flush(); - return AO_FAT_SUCCESS; + ret = AO_FAT_SUCCESS; + goto done; } } - return -AO_FAT_ENOENT; + ret = -AO_FAT_ENOENT; +done: + ao_mutex_put(&ao_fat_mutex); + return ret; } int8_t @@ -1306,34 +1430,6 @@ ao_fat_rename(char old[11], char new[11]) return -AO_FAT_EIO; } -int8_t -ao_fat_readdir(uint16_t *entry, struct ao_fat_dirent *dirent) -{ - uint8_t *dent; - - if (ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS) - return -AO_FAT_EIO; - - for (;;) { - dent = ao_fat_root_get(*entry); - if (!dent) - return -AO_FAT_EDIREOF; - - if (dent[0] == AO_FAT_DENT_END) { - ao_fat_root_put(dent, *entry, 0); - return -AO_FAT_EDIREOF; - } - if (dent[0] != AO_FAT_DENT_EMPTY && (dent[0xb] & 0xf) != 0xf) { - ao_fat_dirent_init(dirent, dent, *entry); - ao_fat_root_put(dent, *entry, 0); - (*entry)++; - return AO_FAT_SUCCESS; - } - ao_fat_root_put(dent, *entry, 0); - (*entry)++; - } -} - #if FAT_COMMANDS static const char *filesystem_errors[] = { @@ -1352,7 +1448,8 @@ ao_fat_mbr_cmd(void) { uint8_t status; - status = ao_fat_setup(); + ao_mutex_get(&ao_fat_mutex); + status = _ao_fat_setup(); if (status == AO_FAT_FILESYSTEM_SUCCESS) { printf ("partition type: %02x\n", partition_type); printf ("partition start: %08x\n", partition_start); @@ -1372,6 +1469,7 @@ ao_fat_mbr_cmd(void) } else { printf ("FAT filesystem not available: %s\n", filesystem_errors[status]); } + ao_mutex_put(&ao_fat_mutex); } struct ao_fat_attr { diff --git a/src/test/ao_fat_test.c b/src/test/ao_fat_test.c index a1bd5fbf..d1309024 100644 --- a/src/test/ao_fat_test.c +++ b/src/test/ao_fat_test.c @@ -158,14 +158,14 @@ ao_fat_entry_raw_read(cluster_t cluster, uint8_t fat) cluster <<= 1; sector = cluster >> SECTOR_SHIFT; offset = cluster & SECTOR_MASK; - buf = ao_fat_sector_get(fat_start + fat * sectors_per_fat + sector); + buf = _ao_fat_sector_get(fat_start + fat * sectors_per_fat + sector); if (!buf) return 0; if (fat32) ret = get_u32(buf + offset); else ret = get_u16(buf + offset); - ao_fat_sector_put(buf, 0); + _ao_fat_sector_put(buf, 0); return ret; } @@ -252,7 +252,7 @@ check_file(dirent_t dent, cluster_t first_cluster, dirent_t *used) fat32 ? !AO_FAT_IS_LAST_CLUSTER(cluster) : !AO_FAT_IS_LAST_CLUSTER16(cluster); cluster = ao_fat_entry_raw_read(cluster, 0)) { - if (!ao_fat_cluster_valid(cluster)) + if (!_ao_fat_cluster_valid(cluster)) fatal("file %d: invalid cluster %08x\n", dent, cluster); if (used[cluster]) fatal("file %d: duplicate cluster %08x also in file %d\n", dent, cluster, used[cluster]-1); @@ -274,7 +274,7 @@ check_fs(void) used = calloc(sizeof (dirent_t), number_cluster); - for (r = 0; (dent = ao_fat_root_get(r)); r++) { + for (r = 0; (dent = _ao_fat_root_get(r)); r++) { cluster_t clusters; offset_t size; cluster_t first_cluster; @@ -287,7 +287,7 @@ check_fs(void) if (fat32) first_cluster |= (cluster_t) get_u16(dent + 0x14) << 16; size = get_u32(dent + 0x1c); - ao_fat_root_put(dent, r, 0); + _ao_fat_root_put(dent, r, 0); if (name[0] == AO_FAT_DENT_END) { break; @@ -308,12 +308,12 @@ check_fs(void) } if (!fat32) { for (; r < root_entries; r++) { - uint8_t *dent = ao_fat_root_get(r); + uint8_t *dent = _ao_fat_root_get(r); if (!dent) fatal("cannot map dent %d\n", r); if (dent[0] != AO_FAT_DENT_END) fatal("found non-zero dent past end %d\n", r); - ao_fat_root_put(dent, r, 0); + _ao_fat_root_put(dent, r, 0); } } else { check_file((dirent_t) -1, root_cluster, used); @@ -536,7 +536,7 @@ do_test(void (*test)(void)) ao_fat_init(); check_bufio("top"); - ao_fat_setup(); + _ao_fat_setup(); check_fs(); check_bufio("after setup"); -- cgit v1.2.3 From 759376cd0aac61c5afce31aed27ef98aba791173 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Mon, 22 Apr 2013 13:50:13 +1200 Subject: altos: update .gitignore files Signed-off-by: Mike Beattie --- .gitignore | 1 + src/test/.gitignore | 1 + 2 files changed, 2 insertions(+) (limited to 'src/test') diff --git a/.gitignore b/.gitignore index 6ae2b864..5dec09a5 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ ao-tidongle.h ao-tools/ao-bitbang/ao-bitbang ao-tools/ao-dbg/ao-dbg ao-tools/ao-dumplog/ao-dumplog +ao-tools/ao-dump-up/ao-dump-up ao-tools/ao-eeprom/ao-eeprom ao-tools/ao-edit-telem/ao-edit-telem ao-tools/ao-list/ao-list diff --git a/src/test/.gitignore b/src/test/.gitignore index 8d79d168..8f74c348 100644 --- a/src/test/.gitignore +++ b/src/test/.gitignore @@ -7,6 +7,7 @@ ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test +ao_fat_test ao_fec_test ao_flight_test_mm ao_flight_test_noisy_accel -- cgit v1.2.3 From aa7eac32adf4c2cdf441991d02411758f2682d1e Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 22 Apr 2013 13:00:26 -0600 Subject: name change from MegaMetrum to TeleMega --- altoslib/AltosConfigData.java | 2 +- altoslib/AltosIdleMonitor.java | 4 +- altoslib/AltosLib.java | 6 +- altosui/AltosDataChooser.java | 2 +- altosui/AltosEepromDownload.java | 2 +- altosui/Makefile.am | 2 +- altosui/altos-windows.nsi.in | 2 +- altosuilib/AltosUSBDevice.java | 6 +- ao-bringup/megametrum.cfg | 4 - ao-bringup/megametrum.gdb | 2 - ao-bringup/telemega.cfg | 4 + ao-bringup/telemega.gdb | 2 + debian/docs | 2 +- doc/altos.xsl | 2 +- doc/megametrum-outline.pdf | Bin 4349 -> 0 bytes doc/megametrum-outline.svg | 244 ------------------------ doc/release-notes-1.2.xsl | 2 +- src/Makefile | 2 +- src/core/ao_fec_rx.c | 2 +- src/core/ao_log.h | 2 +- src/core/ao_log_mega.c | 2 +- src/core/ao_telemetry.c | 2 +- src/drivers/ao_companion.c | 2 +- src/megametrum-v0.1/.gitignore | 2 - src/megametrum-v0.1/Makefile | 131 ------------- src/megametrum-v0.1/ao_megametrum.c | 100 ---------- src/megametrum-v0.1/ao_pins.h | 359 ------------------------------------ src/megametrum-v0.1/stlink-pins | 57 ------ src/stm/ao_i2c_stm.c | 2 +- src/telelco-v0.1/Makefile | 2 +- src/test/Makefile | 2 +- src/test/ao_flight_test.c | 22 +-- telemetrum.inf | 8 +- 33 files changed, 46 insertions(+), 939 deletions(-) delete mode 100644 ao-bringup/megametrum.cfg delete mode 100644 ao-bringup/megametrum.gdb create mode 100644 ao-bringup/telemega.cfg create mode 100644 ao-bringup/telemega.gdb delete mode 100644 doc/megametrum-outline.pdf delete mode 100644 doc/megametrum-outline.svg delete mode 100644 src/megametrum-v0.1/.gitignore delete mode 100644 src/megametrum-v0.1/Makefile delete mode 100644 src/megametrum-v0.1/ao_megametrum.c delete mode 100644 src/megametrum-v0.1/ao_pins.h delete mode 100644 src/megametrum-v0.1/stlink-pins (limited to 'src/test') diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 57605607..2ca5a7a5 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -504,7 +504,7 @@ public class AltosConfigData implements Iterable { switch (log_format) { case AltosLib.AO_LOG_FORMAT_FULL: case AltosLib.AO_LOG_FORMAT_TINY: - case AltosLib.AO_LOG_FORMAT_MEGAMETRUM: + case AltosLib.AO_LOG_FORMAT_TELEMEGA: link.printf("l\n"); read_link(link, "done"); default: diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index c379547f..2e4ddef2 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -52,11 +52,11 @@ public class AltosIdleMonitor extends Thread { } boolean has_sensor_mm(AltosConfigData config_data) { - return config_data.product.startsWith("MegaMetrum"); + return config_data.product.startsWith("TeleMega"); } boolean has_gps(AltosConfigData config_data) { - return config_data.product.startsWith("TeleMetrum") || config_data.product.startsWith("MegaMetrum"); + return config_data.product.startsWith("TeleMetrum") || config_data.product.startsWith("TeleMega"); } AltosRecord sensor_mm(AltosConfigData config_data) throws InterruptedException, TimeoutException { diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 0b5475f7..25d17e72 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -50,7 +50,7 @@ public class AltosLib { public static final int AO_LOG_SERIAL_NUMBER = 2002; public static final int AO_LOG_LOG_FORMAT = 2003; - /* Added for header fields in megametrum files */ + /* Added for header fields in telemega files */ public static final int AO_LOG_BARO_RESERVED = 3000; public static final int AO_LOG_BARO_SENS = 3001; public static final int AO_LOG_BARO_OFF = 3002; @@ -89,7 +89,7 @@ public class AltosLib { public final static int product_telelco = 0x0010; public final static int product_telescience = 0x0011; public final static int product_telepyro =0x0012; - public final static int product_megametrum = 0x0023; + public final static int product_telemega = 0x0023; public final static int product_megadongle = 0x0024; public final static int product_telegps = 0x0025; public final static int product_altusmetrum_min = 0x000a; @@ -215,7 +215,7 @@ public class AltosLib { public static final int AO_LOG_FORMAT_TINY = 2; public static final int AO_LOG_FORMAT_TELEMETRY = 3; public static final int AO_LOG_FORMAT_TELESCIENCE = 4; - public static final int AO_LOG_FORMAT_MEGAMETRUM = 5; + public static final int AO_LOG_FORMAT_TELEMEGA = 5; public static final int AO_LOG_FORMAT_NONE = 127; public static boolean isspace(int c) { diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java index 7de18afb..f914f138 100644 --- a/altosui/AltosDataChooser.java +++ b/altosui/AltosDataChooser.java @@ -75,7 +75,7 @@ public class AltosDataChooser extends JFileChooser { "eeprom")); setFileFilter(new FileNameExtensionFilter("Telemetry file", "telem")); - setFileFilter(new FileNameExtensionFilter("MegaMetrum eeprom file", + setFileFilter(new FileNameExtensionFilter("TeleMega eeprom file", "mega")); setFileFilter(new FileNameExtensionFilter("Flight data file", "telem", "eeprom", "mega")); diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 801d4ec0..a0523b58 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -366,7 +366,7 @@ public class AltosEepromDownload implements Runnable { extension = "science"; CaptureTeleScience(eechunk); break; - case AltosLib.AO_LOG_FORMAT_MEGAMETRUM: + case AltosLib.AO_LOG_FORMAT_TELEMEGA: extension = "mega"; CaptureMega(eechunk); } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 96cf77f2..4bfef47c 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -157,7 +157,7 @@ FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TELEMINI) $(FIRMWARE_TD) ALTUSMETRUM_DOC=$(top_srcdir)/doc/altusmetrum.pdf ALTOS_DOC=$(top_srcdir)/doc/altos.pdf TELEMETRY_DOC=$(top_srcdir)/doc/telemetry.pdf -TEMPLATE_DOC=$(top_srcdir)/doc/telemetrum-outline.pdf $(top_srcdir)/doc/megametrum-outline.pdf +TEMPLATE_DOC=$(top_srcdir)/doc/telemetrum-outline.pdf $(top_srcdir)/doc/telemega-outline.pdf DOC=$(ALTUSMETRUM_DOC) $(ALTOS_DOC) $(TELEMETRY_DOC) $(TEMPLATE_DOC) diff --git a/altosui/altos-windows.nsi.in b/altosui/altos-windows.nsi.in index cde54b41..9886e4a2 100644 --- a/altosui/altos-windows.nsi.in +++ b/altosui/altos-windows.nsi.in @@ -131,7 +131,7 @@ Section "Documentation" File "../doc/altos.pdf" File "../doc/telemetry.pdf" File "../doc/telemetrum-outline.pdf" - File "../doc/megametrum-outline.pdf" + File "../doc/telemega-outline.pdf" SectionEnd Section "Uninstaller" diff --git a/altosuilib/AltosUSBDevice.java b/altosuilib/AltosUSBDevice.java index 5268927c..0f6cbd10 100644 --- a/altosuilib/AltosUSBDevice.java +++ b/altosuilib/AltosUSBDevice.java @@ -72,11 +72,11 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { return matchProduct(AltosUILib.product_teledongle) || matchProduct(AltosUILib.product_teleterra) || matchProduct(AltosUILib.product_telebt) || - matchProduct(AltosUILib.product_megadongle); + matchProduct(AltosUILib.product_telemega); if (want_product == AltosUILib.product_altimeter) return matchProduct(AltosUILib.product_telemetrum) || - matchProduct(AltosUILib.product_megametrum) || + matchProduct(AltosUILib.product_telemega) || matchProduct(AltosUILib.product_telegps); int have_product = getProduct(); @@ -110,4 +110,4 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { return device_list; } -} \ No newline at end of file +} diff --git a/ao-bringup/megametrum.cfg b/ao-bringup/megametrum.cfg deleted file mode 100644 index e95c6f2b..00000000 --- a/ao-bringup/megametrum.cfg +++ /dev/null @@ -1,4 +0,0 @@ -# openocd config for MegaMetrum using the Olimex ARM-USB-OCD dongle - -source /opt/stm32/share/openocd/scripts/interface/olimex-arm-usb-ocd.cfg -source /opt/stm32/share/openocd/scripts/target/stm32l.cfg diff --git a/ao-bringup/megametrum.gdb b/ao-bringup/megametrum.gdb deleted file mode 100644 index 964ae1f3..00000000 --- a/ao-bringup/megametrum.gdb +++ /dev/null @@ -1,2 +0,0 @@ -target remote localhost:3333 -monitor poll diff --git a/ao-bringup/telemega.cfg b/ao-bringup/telemega.cfg new file mode 100644 index 00000000..f6b96c13 --- /dev/null +++ b/ao-bringup/telemega.cfg @@ -0,0 +1,4 @@ +# openocd config for TeleMega using the Olimex ARM-USB-OCD dongle + +source /opt/stm32/share/openocd/scripts/interface/olimex-arm-usb-ocd.cfg +source /opt/stm32/share/openocd/scripts/target/stm32l.cfg diff --git a/ao-bringup/telemega.gdb b/ao-bringup/telemega.gdb new file mode 100644 index 00000000..964ae1f3 --- /dev/null +++ b/ao-bringup/telemega.gdb @@ -0,0 +1,2 @@ +target remote localhost:3333 +monitor poll diff --git a/debian/docs b/debian/docs index 3ac75ad4..dcdb7763 100644 --- a/debian/docs +++ b/debian/docs @@ -7,4 +7,4 @@ doc/telemetry.pdf doc/altos.html doc/altos.pdf doc/telemetrum-outline.pdf -doc/megametrum-outline.pdf +doc/telemega-outline.pdf diff --git a/doc/altos.xsl b/doc/altos.xsl index c301adde..5af94725 100644 --- a/doc/altos.xsl +++ b/doc/altos.xsl @@ -50,7 +50,7 @@ STM32L series from ST Microelectronics. This ARM Cortex-M3 based microcontroller offers low power consumption and a wide variety of built-in peripherals. Altus Metrum uses - this in the MegaMetrum, MegaDongle and TeleLCO projects. + this in the TeleMega, MegaDongle and TeleLCO projects. diff --git a/doc/megametrum-outline.pdf b/doc/megametrum-outline.pdf deleted file mode 100644 index f8fc26e2..00000000 Binary files a/doc/megametrum-outline.pdf and /dev/null differ diff --git a/doc/megametrum-outline.svg b/doc/megametrum-outline.svg deleted file mode 100644 index e8d74d38..00000000 --- a/doc/megametrum-outline.svg +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UP - - diff --git a/doc/release-notes-1.2.xsl b/doc/release-notes-1.2.xsl index 610fa1a2..b254c7b5 100644 --- a/doc/release-notes-1.2.xsl +++ b/doc/release-notes-1.2.xsl @@ -41,7 +41,7 @@ raised, breaking the Descent tab contents. - Add preliminary MegaMetrum support, including configuration, + Add preliminary TeleMega support, including configuration, data download and analysis. diff --git a/src/Makefile b/src/Makefile index d91a235a..e271ddf3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -29,7 +29,7 @@ AVRDIRS=\ telescience-v0.1 telescience-pwm telepyro-v0.1 micropeak ARMDIRS=\ - megametrum-v0.1 megadongle-v0.1 stm-bringup stm-demo telelco-v0.1 \ + telemega-v0.1 megadongle-v0.1 stm-bringup stm-demo telelco-v0.1 \ telescience-v0.2 ifneq ($(shell which sdcc),) diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index 072a9e90..c4f5559a 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -18,7 +18,7 @@ #include #include -#ifdef MEGAMETRUM +#ifdef TELEMEGA #include #endif diff --git a/src/core/ao_log.h b/src/core/ao_log.h index cac78771..a68a40dd 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -43,7 +43,7 @@ extern __pdata enum ao_flight_state ao_log_state; #define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ #define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ #define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ -#define AO_LOG_FORMAT_MEGAMETRUM 5 /* 32 byte typed megametrum records */ +#define AO_LOG_FORMAT_TELEMEGA 5 /* 32 byte typed telemega records */ #define AO_LOG_FORMAT_NONE 127 /* No log at all */ extern __code uint8_t ao_log_format; diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index ba3f7bfc..abf953a6 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -23,7 +23,7 @@ static __xdata uint8_t ao_log_mutex; static __xdata struct ao_log_mega log; -__code uint8_t ao_log_format = AO_LOG_FORMAT_MEGAMETRUM; +__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMEGA; static uint8_t ao_log_csum(__xdata uint8_t *b) __reentrant diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 3aa315c7..03aa48d8 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -29,7 +29,7 @@ static __pdata uint16_t ao_aprs_time; #include #endif -#if defined(MEGAMETRUM) +#if defined(TELEMEGA) #define AO_SEND_MEGA 1 #endif diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 0ebe8429..0f405253 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -18,7 +18,7 @@ #include #include -#ifdef MEGAMETRUM +#ifdef TELEMEGA #define ao_spi_slow(b) #define ao_spi_fast(b) #endif diff --git a/src/megametrum-v0.1/.gitignore b/src/megametrum-v0.1/.gitignore deleted file mode 100644 index b04d3950..00000000 --- a/src/megametrum-v0.1/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -ao_product.h -megametrum-*.elf diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile deleted file mode 100644 index a5fdcbb2..00000000 --- a/src/megametrum-v0.1/Makefile +++ /dev/null @@ -1,131 +0,0 @@ -# -# AltOS build -# -# - -include ../stm/Makefile.defs - -INC = \ - ao.h \ - ao_arch.h \ - ao_arch_funcs.h \ - ao_companion.h \ - ao_data.h \ - ao_sample.h \ - ao_pins.h \ - altitude-pa.h \ - ao_kalman.h \ - ao_product.h \ - ao_ms5607.h \ - ao_hmc5883.h \ - ao_mpu6000.h \ - ao_mma655x.h \ - ao_cc1120_CC1120.h \ - ao_profile.h \ - ao_task.h \ - ao_whiten.h \ - ao_sample_profile.h \ - ao_mpu.h \ - stm32l.h \ - Makefile - -# -# Common AltOS sources -# -# ao_hmc5883.c - -#PROFILE=ao_profile.c -#PROFILE_DEF=-DAO_PROFILE=1 - -#SAMPLE_PROFILE=ao_sample_profile.c \ -# ao_sample_profile_timer.c -#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 - -#STACK_GUARD=ao_mpu_stm.c -#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 - -ALTOS_SRC = \ - ao_interrupt.c \ - ao_product.c \ - ao_romconfig.c \ - ao_cmd.c \ - ao_config.c \ - ao_task.c \ - ao_led.c \ - ao_stdio.c \ - ao_panic.c \ - ao_timer.c \ - ao_mutex.c \ - ao_serial_stm.c \ - ao_gps_skytraq.c \ - ao_gps_report_mega.c \ - ao_ignite.c \ - ao_freq.c \ - ao_dma_stm.c \ - ao_spi_stm.c \ - ao_cc1120.c \ - ao_fec_tx.c \ - ao_fec_rx.c \ - ao_data.c \ - ao_ms5607.c \ - ao_mma655x.c \ - ao_hmc5883.c \ - ao_adc_stm.c \ - ao_beep_stm.c \ - ao_storage.c \ - ao_m25.c \ - ao_usb_stm.c \ - ao_exti_stm.c \ - ao_report.c \ - ao_i2c_stm.c \ - ao_mpu6000.c \ - ao_convert_pa.c \ - ao_log.c \ - ao_log_mega.c \ - ao_sample.c \ - ao_kalman.c \ - ao_flight.c \ - ao_telemetry.c \ - ao_packet_slave.c \ - ao_packet.c \ - ao_companion.c \ - ao_pyro.c \ - ao_aprs.c \ - $(PROFILE) \ - $(SAMPLE_PROFILE) \ - $(STACK_GUARD) - -PRODUCT=MegaMetrum-v0.1 -PRODUCT_DEF=-DMEGAMETRUM -IDPRODUCT=0x0023 - -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g - -PROGNAME=megametrum-v0.1 -PROG=$(PROGNAME)-$(VERSION).elf - -SRC=$(ALTOS_SRC) ao_megametrum.c -OBJ=$(SRC:.c=.o) - -all: $(PROG) - -$(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc - -../altitude-pa.h: make-altitude-pa - nickle $< > $@ - -$(OBJ): $(INC) - -ao_product.h: ao-make-product.5c ../Version - $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ - -distclean: clean - -clean: - rm -f *.o $(PROGNAME)-*.elf - rm -f ao_product.h - -install: - -uninstall: diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c deleted file mode 100644 index fbdab64a..00000000 --- a/src/megametrum-v0.1/ao_megametrum.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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; version 2 of the License. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if HAS_SAMPLE_PROFILE -#include -#endif -#include -#if HAS_STACK_GUARD -#include -#endif - -int -main(void) -{ - ao_clock_init(); - -#if HAS_STACK_GUARD - ao_mpu_init(); -#endif - - ao_task_init(); - ao_serial_init(); - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_GREEN); - ao_timer_init(); - - ao_i2c_init(); - ao_spi_init(); - ao_dma_init(); - ao_exti_init(); - - ao_adc_init(); -#if HAS_BEEP - ao_beep_init(); -#endif - ao_cmd_init(); - -#if HAS_MS5607 - ao_ms5607_init(); -#endif -#if HAS_HMC5883 - ao_hmc5883_init(); -#endif -#if HAS_MPU6000 - ao_mpu6000_init(); -#endif -#if HAS_MMA655X - ao_mma655x_init(); -#endif - - ao_storage_init(); - - ao_flight_init(); - ao_log_init(); - ao_report_init(); - - ao_usb_init(); - ao_gps_init(); - ao_gps_report_mega_init(); - ao_telemetry_init(); - ao_radio_init(); - ao_packet_slave_init(FALSE); - ao_igniter_init(); - ao_companion_init(); - ao_pyro_init(); - - ao_config_init(); -#if AO_PROFILE - ao_profile_init(); -#endif -#if HAS_SAMPLE_PROFILE - ao_sample_profile_init(); -#endif - - ao_start_scheduler(); - return 0; -} diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h deleted file mode 100644 index 4c645871..00000000 --- a/src/megametrum-v0.1/ao_pins.h +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * 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; version 2 of the License. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_PINS_H_ -#define _AO_PINS_H_ - -#define HAS_TASK_QUEUE 1 - -/* 8MHz High speed external crystal */ -#define AO_HSE 8000000 - -/* PLLVCO = 96MHz (so that USB will work) */ -#define AO_PLLMUL 12 -#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) - -/* SYSCLK = 32MHz (no need to go faster than CPU) */ -#define AO_PLLDIV 3 -#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) - -/* HCLK = 32MHz (CPU clock) */ -#define AO_AHB_PRESCALER 1 -#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 - -/* Run APB1 at 16MHz (HCLK/2) */ -#define AO_APB1_PRESCALER 2 -#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 - -/* Run APB2 at 16MHz (HCLK/2) */ -#define AO_APB2_PRESCALER 2 -#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 - -#define HAS_SERIAL_1 1 -#define USE_SERIAL_1_STDIN 0 -#define SERIAL_1_PB6_PB7 0 -#define SERIAL_1_PA9_PA10 1 - -#define HAS_SERIAL_2 0 -#define USE_SERIAL_2_STDIN 0 -#define SERIAL_2_PA2_PA3 0 -#define SERIAL_2_PD5_PD6 0 - -#define HAS_SERIAL_3 1 -#define USE_SERIAL_3_STDIN 0 -#define SERIAL_3_PB10_PB11 0 -#define SERIAL_3_PC10_PC11 1 -#define SERIAL_3_PD8_PD9 0 - -#define ao_gps_getchar ao_serial3_getchar -#define ao_gps_putchar ao_serial3_putchar -#define ao_gps_set_speed ao_serial3_set_speed -#define ao_gps_fifo (ao_stm_usart3.rx_fifo) - -#define HAS_EEPROM 1 -#define USE_INTERNAL_FLASH 0 -#define HAS_USB 1 -#define HAS_BEEP 1 -#define HAS_RADIO 1 -#define HAS_TELEMETRY 1 -#define HAS_APRS 1 - -#define HAS_SPI_1 1 -#define SPI_1_PA5_PA6_PA7 1 /* Barometer */ -#define SPI_1_PB3_PB4_PB5 0 -#define SPI_1_PE13_PE14_PE15 1 /* Accelerometer */ -#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz - -#define HAS_SPI_2 1 -#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */ -#define SPI_2_PD1_PD3_PD4 0 -#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz - -#define SPI_2_PORT (&stm_gpiob) -#define SPI_2_SCK_PIN 13 -#define SPI_2_MISO_PIN 14 -#define SPI_2_MOSI_PIN 15 - -#define HAS_I2C_1 1 -#define I2C_1_PB8_PB9 1 - -#define HAS_I2C_2 1 -#define I2C_2_PB10_PB11 1 - -#define PACKET_HAS_SLAVE 1 -#define PACKET_HAS_MASTER 0 - -#define LOW_LEVEL_DEBUG 0 - -#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN -#define LED_PORT (&stm_gpioc) -#define LED_PIN_RED 8 -#define LED_PIN_GREEN 9 -#define AO_LED_RED (1 << LED_PIN_RED) -#define AO_LED_GREEN (1 << LED_PIN_GREEN) - -#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) - -#define HAS_GPS 1 -#define HAS_FLIGHT 1 -#define HAS_ADC 1 -#define HAS_LOG 1 - -/* - * Igniter - */ - -#define HAS_IGNITE 1 -#define HAS_IGNITE_REPORT 1 - -#define AO_SENSE_DROGUE(p) ((p)->adc.sense[0]) -#define AO_SENSE_MAIN(p) ((p)->adc.sense[1]) -#define AO_IGNITER_CLOSED 400 -#define AO_IGNITER_OPEN 60 - -#define AO_IGNITER_DROGUE_PORT (&stm_gpiod) -#define AO_IGNITER_DROGUE_PIN 6 - -#define AO_IGNITER_MAIN_PORT (&stm_gpiod) -#define AO_IGNITER_MAIN_PIN 7 - -#define AO_PYRO_PORT_0 (&stm_gpiob) -#define AO_PYRO_PIN_0 5 - -#define AO_PYRO_PORT_1 (&stm_gpioe) -#define AO_PYRO_PIN_1 4 - -#define AO_PYRO_PORT_2 (&stm_gpioe) -#define AO_PYRO_PIN_2 6 - -#define AO_PYRO_PORT_3 (&stm_gpioe) -#define AO_PYRO_PIN_3 5 - -/* Number of general purpose pyro channels available */ -#define AO_PYRO_NUM 4 - -#define AO_IGNITER_SET_DROGUE(v) stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v) -#define AO_IGNITER_SET_MAIN(v) stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v) - -/* - * ADC - */ -#define AO_DATA_RING 32 -#define AO_ADC_NUM_SENSE 6 - -struct ao_adc { - int16_t sense[AO_ADC_NUM_SENSE]; - int16_t v_batt; - int16_t v_pbatt; - int16_t accel_ref; - int16_t accel; - int16_t temp; -}; - -#define AO_ADC_SENSE_A 0 -#define AO_ADC_SENSE_A_PORT (&stm_gpioa) -#define AO_ADC_SENSE_A_PIN 0 - -#define AO_ADC_SENSE_B 1 -#define AO_ADC_SENSE_B_PORT (&stm_gpioa) -#define AO_ADC_SENSE_B_PIN 1 - -#define AO_ADC_SENSE_C 2 -#define AO_ADC_SENSE_C_PORT (&stm_gpioa) -#define AO_ADC_SENSE_C_PIN 2 - -#define AO_ADC_SENSE_D 3 -#define AO_ADC_SENSE_D_PORT (&stm_gpioa) -#define AO_ADC_SENSE_D_PIN 3 - -#define AO_ADC_SENSE_E 4 -#define AO_ADC_SENSE_E_PORT (&stm_gpioa) -#define AO_ADC_SENSE_E_PIN 4 - -#define AO_ADC_SENSE_F 22 -#define AO_ADC_SENSE_F_PORT (&stm_gpioe) -#define AO_ADC_SENSE_F_PIN 7 - -#define AO_ADC_V_BATT 8 -#define AO_ADC_V_BATT_PORT (&stm_gpiob) -#define AO_ADC_V_BATT_PIN 0 - -#define AO_ADC_V_PBATT 9 -#define AO_ADC_V_PBATT_PORT (&stm_gpiob) -#define AO_ADC_V_PBATT_PIN 1 - -#define AO_ADC_ACCEL_REF 10 -#define AO_ADC_ACCEL_REF_PORT (&stm_gpioc) -#define AO_ADC_ACCEL_REF_PIN 0 - -#define AO_ADC_ACCEL 11 -#define AO_ADC_ACCEL_PORT (&stm_gpioc) -#define AO_ADC_ACCEL_PIN 1 - -#define AO_ADC_TEMP 16 - -#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \ - (1 << STM_RCC_AHBENR_GPIOEEN) | \ - (1 << STM_RCC_AHBENR_GPIOBEN) | \ - (1 << STM_RCC_AHBENR_GPIOCEN)) - -#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 4) - -#define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT -#define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN -#define AO_ADC_PIN1_PORT AO_ADC_SENSE_B_PORT -#define AO_ADC_PIN1_PIN AO_ADC_SENSE_B_PIN -#define AO_ADC_PIN2_PORT AO_ADC_SENSE_C_PORT -#define AO_ADC_PIN2_PIN AO_ADC_SENSE_C_PIN -#define AO_ADC_PIN3_PORT AO_ADC_SENSE_D_PORT -#define AO_ADC_PIN3_PIN AO_ADC_SENSE_D_PIN -#define AO_ADC_PIN4_PORT AO_ADC_SENSE_E_PORT -#define AO_ADC_PIN4_PIN AO_ADC_SENSE_E_PIN -#define AO_ADC_PIN5_PORT AO_ADC_SENSE_F_PORT -#define AO_ADC_PIN5_PIN AO_ADC_SENSE_F_PIN -#define AO_ADC_PIN6_PORT AO_ADC_V_BATT_PORT -#define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN -#define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT -#define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN -#define AO_ADC_PIN8_PORT AO_ADC_ACCEL_REF_PORT -#define AO_ADC_PIN8_PIN AO_ADC_ACCEL_REF_PIN -#define AO_ADC_PIN9_PORT AO_ADC_ACCEL_PORT -#define AO_ADC_PIN9_PIN AO_ADC_ACCEL_PIN - -#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 5) - -#define AO_ADC_SQ1 AO_ADC_SENSE_A -#define AO_ADC_SQ2 AO_ADC_SENSE_B -#define AO_ADC_SQ3 AO_ADC_SENSE_C -#define AO_ADC_SQ4 AO_ADC_SENSE_D -#define AO_ADC_SQ5 AO_ADC_SENSE_E -#define AO_ADC_SQ6 AO_ADC_SENSE_F -#define AO_ADC_SQ7 AO_ADC_V_BATT -#define AO_ADC_SQ8 AO_ADC_V_PBATT -#define AO_ADC_SQ9 AO_ADC_ACCEL_REF -#define AO_ADC_SQ10 AO_ADC_ACCEL -#define AO_ADC_SQ11 AO_ADC_TEMP - -/* - * Pressure sensor settings - */ -#define HAS_MS5607 1 -#define HAS_MS5611 0 -#define AO_MS5607_PRIVATE_PINS 1 -#define AO_MS5607_CS_PORT (&stm_gpioc) -#define AO_MS5607_CS_PIN 4 -#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) -#define AO_MS5607_MISO_PORT (&stm_gpioa) -#define AO_MS5607_MISO_PIN 6 -#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) -#define AO_MS5607_SPI_INDEX AO_SPI_1_PA5_PA6_PA7 - -/* - * SPI Flash memory - */ - -#define M25_MAX_CHIPS 1 -#define AO_M25_SPI_CS_PORT (&stm_gpiod) -#define AO_M25_SPI_CS_MASK (1 << 3) -#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15 - -/* - * Radio (cc1120) - */ - -/* gets pretty close to 434.550 */ - -#define AO_RADIO_CAL_DEFAULT 0x6ca333 - -#define AO_FEC_DEBUG 0 -#define AO_CC1120_SPI_CS_PORT (&stm_gpioc) -#define AO_CC1120_SPI_CS_PIN 5 -#define AO_CC1120_SPI_BUS AO_SPI_2_PB13_PB14_PB15 -#define AO_CC1120_SPI stm_spi2 - -#define AO_CC1120_INT_PORT (&stm_gpioc) -#define AO_CC1120_INT_PIN 14 -#define AO_CC1120_MCU_WAKEUP_PORT (&stm_gpioc) -#define AO_CC1120_MCU_WAKEUP_PIN (0) - -#define AO_CC1120_INT_GPIO 2 -#define AO_CC1120_INT_GPIO_IOCFG CC1120_IOCFG2 - -#define AO_CC1120_MARC_GPIO 3 -#define AO_CC1120_MARC_GPIO_IOCFG CC1120_IOCFG3 - - -#define HAS_BOOT_RADIO 0 - -/* - * Mag sensor (hmc5883) - */ - -#define HAS_HMC5883 0 -#define AO_HMC5883_INT_PORT (&stm_gpioc) -#define AO_HMC5883_INT_PIN 12 -#define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) - -/* - * mpu6000 - */ - -#define HAS_MPU6000 1 -#define AO_MPU6000_INT_PORT (&stm_gpioc) -#define AO_MPU6000_INT_PIN 13 -#define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) - -#define HAS_HIGHG_ACCEL 0 - -/* - * mma655x - */ - -#define HAS_MMA655X 1 -#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15 -#define AO_MMA655X_CS_PORT (&stm_gpiod) -#define AO_MMA655X_CS_PIN 4 - -#define NUM_CMDS 16 - -/* - * Companion - */ - -#define AO_COMPANION_CS_PORT (&stm_gpiod) -#define AO_COMPANION_CS_PIN (0) -#define AO_COMPANION_SPI_BUS AO_SPI_2_PB13_PB14_PB15 - -/* - * Monitor - */ - -#define HAS_MONITOR 0 -#define LEGACY_MONITOR 0 -#define HAS_MONITOR_PUT 1 -#define AO_MONITOR_LED 0 -#define HAS_RSSI 0 - -/* - * Profiling Viterbi decoding - */ - -#ifndef AO_PROFILE -#define AO_PROFILE 0 -#endif - -#endif /* _AO_PINS_H_ */ diff --git a/src/megametrum-v0.1/stlink-pins b/src/megametrum-v0.1/stlink-pins deleted file mode 100644 index 390f8e5d..00000000 --- a/src/megametrum-v0.1/stlink-pins +++ /dev/null @@ -1,57 +0,0 @@ -ST discovery card pins - -1 AIN-1 -2 JTCK -3 GND -4 JTMS -5 NRST -6 SWO - -MegaMetrum v0.1 misc connector - -1 GND -2 reset_n -3 boot0 -4 tx1 -5 rx1 -6 +3.3V -7 GND -8 jtms -9 jtck -10 jtdi -11 jtdo -12 jntrst -13 sda2 -14 scl2 -15 pe1 -16 pe0 - -For debugging: - - ST MM v0.1 -JTCK 2 9 -GND 3 7 -JTMS 4 8 -NRST 5 2 - -Altus Metrum STM32L standard debug connector (4 pin MicoMaTch): - - TL ST -GND 1 3 -NRST 2 5 -SWDIO 3 4 -SWCLK 4 2 - -Altus Metrum standard 4-pin connector to MegaMetrum v0.1 misc connector: - - AMstd MM v0.1 -gnd 1 1 -nrst 2 2 -swdio 3 8 -swclk 4 9 - -MegaAccel: - -Jumpers -PC0 (pin15) (blue) PE0 (pin97) accel_ref (debug 16) -PC1 (pin16) (green) PE1 (pin98) accel (debug 15) diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 779e2275..809b5c6f 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -36,7 +36,7 @@ static uint16_t ao_i2c_addr[STM_NUM_I2C]; uint8_t ao_i2c_mutex[STM_NUM_I2C]; # define I2C_HIGH_SLOW 5000 /* ns, 100kHz clock */ -#ifdef MEGAMETRUM +#ifdef TELEMEGA # define I2C_HIGH_FAST 2000 /* ns, 167kHz clock */ #else # define I2C_HIGH_FAST 1000 /* ns, 333kHz clock */ diff --git a/src/telelco-v0.1/Makefile b/src/telelco-v0.1/Makefile index d2702dd6..a4a83d02 100644 --- a/src/telelco-v0.1/Makefile +++ b/src/telelco-v0.1/Makefile @@ -61,7 +61,7 @@ ALTOS_SRC = \ ao_radio_cmac_cmd.c PRODUCT=TeleLCO-v0.1 -PRODUCT_DEF=-DMEGAMETRUM +PRODUCT_DEF=-DTELEMEGA IDPRODUCT=0x0023 CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g diff --git a/src/test/Makefile b/src/test/Makefile index 991bdbfc..a62b59c5 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -30,7 +30,7 @@ ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kal cc $(CFLAGS) -o $@ -DFORCE_ACCEL=1 ao_flight_test.c ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS) - cc -DMEGAMETRUM=1 $(CFLAGS) -o $@ $< -lm + cc -DTELEMEGA=1 $(CFLAGS) -o $@ $< -lm ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h cc $(CFLAGS) -o $@ $< diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index cdd1f236..99bed7ee 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -35,7 +35,7 @@ #define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) #define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) -#if MEGAMETRUM +#if TELEMEGA #define AO_ADC_NUM_SENSE 6 #define HAS_MS5607 1 #define HAS_MPU6000 1 @@ -195,7 +195,7 @@ struct ao_cmds { #define ao_xmemcmp(d,s,c) memcmp(d,s,c) #define AO_NEED_ALTITUDE_TO_PRES 1 -#if MEGAMETRUM +#if TELEMEGA #include "ao_convert_pa.c" #include struct ao_ms5607_prom ms5607_prom; @@ -333,7 +333,7 @@ ao_insert(void) #else double accel = 0.0; #endif -#if MEGAMETRUM +#if TELEMEGA double height; ao_ms5607_convert(&ao_data_static.ms5607_raw, &ao_data_static.ms5607_cooked); @@ -373,7 +373,7 @@ ao_insert(void) if (!ao_summary) { printf("%7.2f height %8.2f accel %8.3f " -#if MEGAMETRUM +#if TELEMEGA "roll %8.3f angle %8.3f qangle %8.3f " "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f " #endif @@ -381,7 +381,7 @@ ao_insert(void) time, height, accel, -#if MEGAMETRUM +#if TELEMEGA ao_mpu6000_gyro(ao_sample_roll_angle) / 100.0, ao_mpu6000_gyro(ao_sample_angle) / 100.0, ao_sample_qangle, @@ -555,7 +555,7 @@ int32(uint8_t *bytes, int off) static int log_format; -#if MEGAMETRUM +#if TELEMEGA static double ao_vec_norm(double x, double y, double z) @@ -774,7 +774,7 @@ ao_sleep(void *wchan) for (;;) { if (ao_records_read > 2 && ao_flight_state == ao_flight_startup) { -#if MEGAMETRUM +#if TELEMEGA ao_data_static.mpu6000 = ao_ground_mpu6000; #else ao_data_static.adc.accel = ao_flight_ground_accel; @@ -800,8 +800,8 @@ ao_sleep(void *wchan) if (words[nword] == NULL) break; } -#if MEGAMETRUM - if (log_format == AO_LOG_FORMAT_MEGAMETRUM && nword == 30 && strlen(words[0]) == 1) { +#if TELEMEGA + if (log_format == AO_LOG_FORMAT_TELEMEGA && nword == 30 && strlen(words[0]) == 1) { int i; struct ao_ms5607_value value; @@ -885,7 +885,7 @@ ao_sleep(void *wchan) continue; } #else - if (nword == 4 && log_format != AO_LOG_FORMAT_MEGAMETRUM) { + if (nword == 4 && log_format != AO_LOG_FORMAT_TELEMEGA) { type = words[0][0]; tick = strtoul(words[1], NULL, 16); a = strtoul(words[2], NULL, 16); @@ -1002,7 +1002,7 @@ ao_sleep(void *wchan) if (type != 'F' && !ao_flight_started) continue; -#if MEGAMETRUM +#if TELEMEGA (void) a; (void) b; #else diff --git a/telemetrum.inf b/telemetrum.inf index 91416bca..386dd286 100755 --- a/telemetrum.inf +++ b/telemetrum.inf @@ -30,7 +30,7 @@ DefaultDestDir = 12 %TeleScience% = AltusMetrum.Install, USB\VID_FFFE&PID_0011, AltusMetrumSerial %TelePyro% = AltusMetrum.Install, USB\VID_FFFE&PID_0012, AltusMetrumSerial %TeleShield% = AltusMetrum.Install, USB\VID_FFFE&PID_0013, AltusMetrumSerial -%MegaMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial +%TeleMega% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial %MegaDongle = AltusMetrum.Install, USB\VID_FFFE&PID_0024, AltusMetrumSerial %TeleGPS% = AltusMetrum.Install, USB\VID_FFFE&PID_0025, AltusMetrumSerial %AltusMetrum26% = AltusMetrum.Install, USB\VID_FFFE&PID_0026, AltusMetrumSerial @@ -52,7 +52,7 @@ DefaultDestDir = 12 %TeleScience% = AltusMetrum.Install, USB\VID_FFFE&PID_0011, AltusMetrumSerial %TelePyro% = AltusMetrum.Install, USB\VID_FFFE&PID_0012, AltusMetrumSerial %TeleShield% = AltusMetrum.Install, USB\VID_FFFE&PID_0013, AltusMetrumSerial -%MegaMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial +%TeleMega% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial %MegaDongle = AltusMetrum.Install, USB\VID_FFFE&PID_0024, AltusMetrumSerial %TeleGPS% = AltusMetrum.Install, USB\VID_FFFE&PID_0025, AltusMetrumSerial %AltusMetrum26% = AltusMetrum.Install, USB\VID_FFFE&PID_0026, AltusMetrumSerial @@ -74,7 +74,7 @@ DefaultDestDir = 12 %TeleScience% = AltusMetrum.Install, USB\VID_FFFE&PID_0011, AltusMetrumSerial %TelePyro% = AltusMetrum.Install, USB\VID_FFFE&PID_0012, AltusMetrumSerial %TeleShield% = AltusMetrum.Install, USB\VID_FFFE&PID_0013, AltusMetrumSerial -%MegaMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial +%TeleMega% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial %MegaDongle = AltusMetrum.Install, USB\VID_FFFE&PID_0024, AltusMetrumSerial %TeleGPS% = AltusMetrum.Install, USB\VID_FFFE&PID_0025, AltusMetrumSerial %AltusMetrum26% = AltusMetrum.Install, USB\VID_FFFE&PID_0026, AltusMetrumSerial @@ -96,7 +96,7 @@ DefaultDestDir = 12 %TeleScience% = AltusMetrum.Install, USB\VID_FFFE&PID_0011, AltusMetrumSerial %TelePyro% = AltusMetrum.Install, USB\VID_FFFE&PID_0012, AltusMetrumSerial %TeleShield% = AltusMetrum.Install, USB\VID_FFFE&PID_0013, AltusMetrumSerial -%MegaMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial +%TeleMega% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial %MegaDongle = AltusMetrum.Install, USB\VID_FFFE&PID_0024, AltusMetrumSerial %TeleGPS% = AltusMetrum.Install, USB\VID_FFFE&PID_0025, AltusMetrumSerial %AltusMetrum26% = AltusMetrum.Install, USB\VID_FFFE&PID_0026, AltusMetrumSerial -- cgit v1.2.3