X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=rmslog%2Fmain.c;h=95d988ce0016d8e8a5bd0570aa644f2427584be9;hb=406d9f4c57a7586103a749bcae7e83f8db08b879;hp=663386f45c0723008699f85f6d76a1abdf6c8d69;hpb=d628a65a3e1ab1a3e3f11dcbd65bca85174d36a9;p=rmslog.git diff --git a/rmslog/main.c b/rmslog/main.c index 663386f..95d988c 100644 --- a/rmslog/main.c +++ b/rmslog/main.c @@ -1,122 +1,235 @@ -/** - * \file - * - * - * \author Andrea Righi - * - * \brief Kernel project. - * - * This is a minimalist kernel project: it just initializes the hardware and - * creates an independent process to blink an LED, while the main loop - * continues to monitor the stack utilization of all the processes. + * This application records all incoming data from an RS-232 serial port + * to a file on a FAT-formatted SD card. It can be used to log kernel + * console messages. */ +// Configuration +#define FILE_NAME "log.txt" +#define FILE_NAME_PATTERN "log%04d.txt" +#define FILE_OVERWRITE 0 +#define FILE_PREALLOC_SIZE 102400 + + #include "hw/hw_led.h" +#define LOG_LEVEL 3 +#include #include #include #include -#include -#include +#include +#include +#include +#include +#include #include -#include -static Serial out; +#include // sprintf() +#include // strcmp() -static void init(void) + +// Our serial port +static Serial ser; + +// FAT global state +struct fat_fs_struct *fs; +struct partition_struct *partition; +struct fat_dir_struct *dd; +struct fat_dir_entry_struct dir_entry; +struct fat_file_struct *fd; + + +static void fat_init(void) { - /* Enable all the interrupts */ - IRQ_ENABLE; + partition = partition_open( + sd_raw_read, + sd_raw_read_interval, + sd_raw_write, + sd_raw_write_interval, + 0 + ); + + if (!partition) + { + // If the partition did not open, assume the storage device + // is a "superfloppy", i.e. has no MBR. + partition = partition_open( + sd_raw_read, + sd_raw_read_interval, + sd_raw_write, + sd_raw_write_interval, + 0 + ); + } + if (!partition) + { + ASSERT(0); for(;;) {} + } + + if (!(fs = fat_open(partition))) + { + ASSERT(0); for(;;) {} + } + + // Open root directory + fat_get_dir_entry_of_path(fs, "/", &dir_entry); + if (!(dd = fat_open_dir(fs, &dir_entry))) + { + ASSERT(0); for(;;) {} + } +} + +static uint8_t find_file_in_dir(UNUSED_ARG(struct fat_fs_struct *, fs), struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry) +{ + fat_reset_dir(dd); //Make sure to start from the beginning of the directory! + while(fat_read_dir(dd, dir_entry)) + { + if(strcmp(dir_entry->long_name, name) == 0) + { + //fat_reset_dir(dd); + return 1; + } + } + + return 0; +} + +static struct fat_file_struct *open_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name) +{ + struct fat_dir_entry_struct file_entry; + if(!find_file_in_dir(fs, dd, name, &file_entry)) + return 0; + + return fat_open_file(fs, &file_entry); +} + +static void init(void) +{ /* Initialize debugging module (allow kprintf(), etc.) */ kdbg_init(); + /* Initialize system timer */ timer_init(); - /* - * XXX: Arduino has a single UART port that was previously - * initialized for debugging purpose. - * In order to activate the serial driver you should disable - * the debugging module. - */ -#if 0 + + /* Enable all the interrupts */ + IRQ_ENABLE; + + /* Kernel initialization: processes */ + proc_init(); + /* Initialize UART0 */ - ser_init(&out, SER_UART0); - /* Configure UART0 to work at 115.200 bps */ - ser_setbaudrate(&out, 115200); -#else - (void)out; -#endif - /* Initialize LED driver */ + ser_init(&ser, SER_UART0); + + //FIXME: The 16MHz arduino clock causes 3.5% baudrate error at 115200 + //ser_setbaudrate(&ser, 115200); + ser_setbaudrate(&ser, 57600); + UCSR0A = BV(U2X0); + + // At this baud rate, we're fast enought to write a continuous + // input stream to the SD card + //ser_setbaudrate(&ser, 19200); + + // Initialize LED driver LED_INIT(); /* - * Kernel initialization: processes (allow to create and dispatch - * processes using proc_new()). + * This gives avrdude some time to start reflashing in case + * the bug caused the program to do continous serial output */ - proc_init(); -} + timer_delay(1000); -static void NORETURN led_process(void) -{ - int i; - - /* Periodically blink the led (toggle each 100 ms) */ - for (i = 0; ; i = !i) + DDRB |= BV(PORTB0) | BV(PORTB2) | BV(PORTB3) | BV(PORTB5); + if (!sd_raw_init()) { - if (i) - LED_ON(); - else - LED_OFF(); - timer_delay(100); + ASSERT(0); for(;;) {} } + + fat_init(); } + int main(void) { - /* Hardware initialization */ init(); - /* Create a new child process */ - proc_new(led_process, NULL, KERN_MINSTACKSIZE * 2, NULL); + size_t size; + bool sync_pending = false; + char buf[256]; - /* - * The main process is kept to periodically report the stack - * utilization of all the processes (1 probe per second). - */ - while (1) + #if FILE_OVERWRITE + { + if(!fat_create_file(dd, FILE_NAME, &dir_entry)) + { + fat_delete_file(fs, &dir_entry); + fat_create_file(dd, FILE_NAME, &dir_entry); + } + + fd = open_file_in_dir(fs, dd, FILE_NAME); + } + #else /* Generate a new filename */ + { + int n; + char filename[8+1+3+1]; + + for (n = 0; /**/; ++n) + { + sprintf(filename, FILE_NAME_PATTERN, n); + if (fat_create_file(dd, filename, &dir_entry)) + break; + } + + fd = open_file_in_dir(fs, dd, filename); + } + #endif + + #if FILE_PREALLOC_SIZE + { + LED_ON(); + memset(buf, ' ', sizeof(buf)); + for (int i = 0; i < (int)(FILE_PREALLOC_SIZE / sizeof(buf)); ++i) + fat_write_file(fd, (void *)buf, sizeof(buf)); + + int32_t offset = 0; + fat_seek_file(fd, &offset, FAT_SEEK_SET); + LED_OFF(); + } + #endif + + for (;;) { - monitor_report(); - timer_delay(1000); + if ((size = ser_read(&ser, buf, sizeof(buf))) != 0) + { + LED_ON(); + fat_write_file(fd, (void *)buf, size); + sync_pending = true; + LED_OFF(); + } + else + { + serstatus_t err = ser_getstatus(&ser); + if (err & ~SERRF_RXTIMEOUT) + { + LED_ON(); + kfile_printf(&ser.fd, "\r\n*** err=%d ***\r\n", err); + } + ser_setstatus(&ser, 0); + + if (sync_pending) + { + LED_ON(); + sd_raw_sync(); + LED_OFF(); + sync_pending = false; + } + } } + fat_close_file(fd); }