📄 fat16test.cpp
字号:
// fat16test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
//int _tmain(int argc, _TCHAR* argv[])
//{
// return 0;
//}
/*
* Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <string.h>
extern "C" {
#include ".\\fs\\fat16.h"
#include ".\\fs\\fat16_config.h"
#include ".\\fs\\partition.h"
#include ".\\fs\\uartsim.h"
#include ".\\fs\\blkmdd.h"
#include ".\\fs\\stdwrap.h"
#define PSTR(v) v
#define DEBUG 1
/**
* \mainpage MMC/SD card example application
*
* This project is a small test application which implements read and write
* support for MMC and SD cards.
*
* It includes
* - low-level \link BlkMdd MMC read/write routines \endlink
* - \link partition partition table support \endlink
* - a simple \link fat16 FAT16 read/write implementation \endlink
*
* \section circuit The circuit
* The curcuit board is a self-made and self-soldered board consisting of a single
* copper layer and standard DIL components, except of the MMC/SD card connector.
*
* The connector is soldered to the bottom side of the board. It has a simple
* eject button which, when a card is inserted, needs some space beyond the connector
* itself. As an additional feature the connector has two electrical switches
* to detect wether a card is inserted and wether this card is write-protected.
*
* I used two microcontrollers during development, the Atmel ATmega8 with 8kBytes
* of flash, and its pin-compatible alternative, the ATmega168 with 16kBytes flash.
* The first one is the one I started with, but when I implemented FAT16 write
* support, I ran out of flash space and switched to the ATmega168.
*
* \section pictures Pictures
* \image html pic01.jpg "The circuit board used to implement and test this application."
* \image html pic02.jpg "The MMC/SD card connector on the soldering side of the circuit board."
*
* \section software The software
* The software is written in pure standard ANSI-C. Sure, it might not be the
* smallest or the fastest one, but I think it is quite flexible.
*
* I implemented a simple command prompt which is accessible via the UART at 9600 Baud. With
* commands similiar to the Unix shell you can browse different directories, read and write
* files, create new ones and delete them again. Not all commands are available in all
* software configurations.
* - <tt>cat \<file\></tt>\n
* Writes a hexdump of \<file\> to the terminal.
* - <tt>cd \<directory\></tt>\n
* Changes current working directory to \<directory\>.
* - <tt>disk</tt>\n
* Shows card manufacturer, status, filesystem capacity and free storage space.
* - <tt>ls</tt>\n
* Shows the content of the current directory.
* - <tt>mkdir \<directory\></tt>\n
* Creates a directory called \<directory\>.
* - <tt>rm \<file\></tt>\n
* Deletes \<file\>.
* - <tt>sync</tt>\n
* Ensures all buffered data is written to the card.
* - <tt>touch \<file\></tt>\n
* Creates \<file\>.
* - <tt>write \<file\> \<offset\></tt>\n
* Writes text to \<file\>, starting from \<offset\>. The text is read
* from the UART, line by line. Finish with an empty line.
*
* \htmlonly
* <p>
* The following table shows some typical code sizes in bytes, using the 20061101 release with malloc()/free():
* </p>
*
* <table border="1" cellpadding="2">
* <tr>
* <th>layer</th>
* <th>code size</th>
* <th>static RAM usage</th>
* </tr>
* <tr>
* <td>MMC/SD (read-only)</td>
* <td align="right">1576</td>
* <td align="right">0</td>
* </tr>
* <tr>
* <td>MMC/SD (read-write)</td>
* <td align="right">2202</td>
* <td align="right">517</td>
* </tr>
* <tr>
* <td>Partition</td>
* <td align="right">418</td>
* <td align="right">0</td>
* </tr>
* <tr>
* <td>FAT16 (read-only)</td>
* <td align="right">3834</td>
* <td align="right">0</td>
* </tr>
* <tr>
* <td>FAT16 (read-write)</td>
* <td align="right">7932</td>
* <td align="right">0</td>
* </tr>
* </table>
*
* <p>
* The static RAM in the read-write case is used for buffering memory card
* access. Without this buffer, implementation would have been much more complicated.
* </p>
*
* <p>
* Please note that the numbers above do not include the C library functions
* used, e.g. malloc()/free() and some string functions. These will raise the
* numbers somewhat if they are not already used in other program parts.
* </p>
*
* <p>
* When opening a partition, filesystem, file or directory, a little amount
* of dynamic RAM is used, as listed in the following table. Alternatively,
* the same amount of static RAM can be used.
* </p>
*
* <table border="1" cellpadding="2">
* <tr>
* <th>descriptor</th>
* <th>dynamic/static RAM</th>
* </tr>
* <tr>
* <td>partition</td>
* <td align="right">17</td>
* </tr>
* <tr>
* <td>filesystem</td>
* <td align="right">26</td>
* </tr>
* <tr>
* <td>file</td>
* <td align="right">51</td>
* </tr>
* <tr>
* <td>directory</td>
* <td align="right">47</td>
* </tr>
* </table>
*
* \endhtmlonly
*
* \section adaptation Adapting the software to your needs
* The only hardware dependent part is the communication
* layer talking to the memory card. The other parts like partition table and FAT16
* support are completely independent, you could use them even for managing
* Compact Flash cards or standard ATAPI hard disks.
*
* By changing the MCU* variables in the Makefile, you can use other Atmel
* microcontrollers or different clock speeds. You might also want to change
* the configuration defines in the files fat16_config.h, partition_config.h,
* BlkMdd_config.h and sd-reader_config.h. For example, you could disable
* write support completely if you only need read support.
*
* \section bugs Bugs or comments?
* If you have comments or found a bug in the software - there might be some
* of them - you may contact me per mail at feedback@roland-riegel.de.
*
* \section acknowledgements Acknowledgements
* Thanks go to Ulrich Radig, who explained on his homepage how to interface
* MMC cards to the Atmel microcontroller (http://www.ulrichradig.de/).
* I adapted his work for my circuit. Although this is a very simple
* solution, I had no problems using it.
*
* \section copyright Copyright 2006-2007 by Roland Riegel
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation (http://www.gnu.org/copyleft/gpl.html).
*/
static uint8_t read_line(char* buffer, uint8_t buffer_length);
static uint32_t strtolong(const char* str);
static uint8_t find_file_in_dir(struct fat16_fs_struct* fs, struct fat16_dir_struct* dd, const char* name, struct fat16_dir_entry_struct* dir_entry);
static struct fat16_file_struct* open_file_in_dir(struct fat16_fs_struct* fs, struct fat16_dir_struct* dd, const char* name);
static uint8_t print_disk_info(const struct fat16_fs_struct* fs);
int _tmain()
{
struct partition_struct* partition;
struct fat16_fs_struct* fs;
struct fat16_dir_entry_struct directory;
struct fat16_dir_struct* dd;
struct fat16_dir_entry_struct subdir_entry;
char buffer[24];
char* command;
struct fat16_dir_struct* dd_new;
/* setup uart */
uart_init();
/* setup sd card slot */
if(!BlkMdd_Startup())
{
#if DEBUG
uart_puts_p(PSTR("MMC/SD initialization failed\n"));
#endif
return 1;
}
/* open first partition */
partition = partition_open(BlkMdd_read,
BlkMdd_read_interval,
BlkMdd_write,
BlkMdd_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(BlkMdd_read,
BlkMdd_read_interval,
BlkMdd_write,
BlkMdd_write_interval,
-1
);
if(!partition)
{
#if DEBUG
uart_puts_p(PSTR("opening partition failed\n"));
#endif
return 1;
}
}
/* open file system */
fs = fat16_open(partition);
if(!fs)
{
#if DEBUG
uart_puts_p(PSTR("opening filesystem failed\n"));
#endif
return 1;
}
/* open root directory */
fat16_get_dir_entry_of_path(fs, "/", &directory);
dd = fat16_open_dir(fs, &directory);
if(!dd)
{
#if DEBUG
uart_puts_p(PSTR("opening root directory failed\n"));
#endif
return 1;
}
/* print some card information as a boot message */
print_disk_info(fs);
/* provide a simple shell */
while(1)
{
/* print prompt */
uart_putc('>');
uart_putc(' ');
/* read command */
command = buffer;
if(read_line(command, sizeof(buffer)) < 1)
continue;
/* execute command */
if(strncmp(command, PSTR("cd "), 3) == 0)
{
command += 3;
if(command[0] == '\0')
continue;
/* change directory */
if(find_file_in_dir(fs, dd, command, &subdir_entry))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -