You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1363 lines
37 KiB
C
1363 lines
37 KiB
C
/*
|
|
* main.c
|
|
*
|
|
* Created on: 22 íîÿá. 2018 ã.
|
|
* Author: maxx
|
|
*/
|
|
/*
|
|
* FatFS SD-card(SPI_SD-CS PB.0) monitor and test LFN
|
|
* Adapted for m1284p Eclipse 16Mhz
|
|
* (c) Ibragimov M. Russia Togliatty 17/12/2018
|
|
*
|
|
* Optimization notes:
|
|
* -Os, not work!! (google reading says GCC version bug (FATFS monitos xprintf.. related))
|
|
* -O3 - OK but size file huge
|
|
* -O2 - is OK
|
|
* Decide not use xitoa by Elm Chang (any way -Os not work :(( )
|
|
*
|
|
* Two main functions for FATFS:
|
|
* 1. fatfs_tst() - Quick test base functions FATFS open-sd/work_with_directory/read-write_file etc..
|
|
* 2. fatfs_monitor() - Command terminal for FATFS test
|
|
* Commands sequence example:
|
|
*
|
|
* >di 0
|
|
* >fi 0 1
|
|
* >fs
|
|
* >fl
|
|
* >fo 1 readme.txt
|
|
* >fd 100
|
|
* >fc
|
|
*
|
|
* Warning!!
|
|
* To work properly, need disconnect SPI programmer (SD-Card not work with MKII programmer connected!!)
|
|
*
|
|
*/
|
|
|
|
#include <avr/io.h>
|
|
#include <util/delay.h>
|
|
#include <avr/interrupt.h>
|
|
#include <avr/pgmspace.h>
|
|
#include <compat/deprecated.h> //sbi, cbi etc..
|
|
#include "avr/wdt.h" // WatchDog
|
|
#include <stdio.h> // printf etc..
|
|
#include "uart_extd.h"
|
|
|
|
//#include <stdlib.h> // itoa etc..
|
|
|
|
//******************************* Fat FS declare related: BEGIN
|
|
#include "string.h"
|
|
#include "ff.h"
|
|
#include "diskio.h"
|
|
#include "integer.h"
|
|
//#include "xitoa.h" // ChaN light libs similar like <stdio.h> && <stdlib.h>
|
|
|
|
#define EN_FS_MONITOR 0
|
|
//#define EN_FS_MONITOR 1 //works only with -O3/-O2/-O1/-O0 - preffered use -O2
|
|
|
|
typedef char PROGMEM prog_char;
|
|
#define xprintf printf_P
|
|
#define xputc uart_putc
|
|
#define xputs printf_P
|
|
#define xsprintf sprintf_P
|
|
|
|
|
|
DWORD AccSize; /* Work register for fs command */
|
|
WORD AccFiles, AccDirs;
|
|
FILINFO Finfo;
|
|
#if _USE_LFN
|
|
char Lfname[_MAX_LFN+1];
|
|
#endif
|
|
|
|
char Line[80]; /* Console input buffer */
|
|
BYTE Buff[2048]; /* Working buffer */
|
|
|
|
FATFS FatFs[_VOLUMES]; /* File system object for each logical drive */ //!! Urgent must be always global!!
|
|
FIL File[2]; /* File object */
|
|
DIR Dir; /* Directory object */
|
|
|
|
|
|
BYTE RtcOk; /* RTC is available */
|
|
|
|
volatile UINT Timer; /* Performance timer (100Hz increment) (for FatFS test)*/
|
|
|
|
/*----------------------------------------------*/
|
|
/* Get a value of the string */
|
|
/*----------------------------------------------*/
|
|
/* "123 -5 0x3ff 0b1111 0377 w "
|
|
^ 1st call returns 123 and next ptr
|
|
^ 2nd call returns -5 and next ptr
|
|
^ 3rd call returns 1023 and next ptr
|
|
^ 4th call returns 15 and next ptr
|
|
^ 5th call returns 255 and next ptr
|
|
^ 6th call fails and returns 0
|
|
*/
|
|
|
|
int xatoi ( /* 0:Failed, 1:Successful */
|
|
char **str, /* Pointer to pointer to the string */
|
|
long *res /* Pointer to the valiable to store the value */
|
|
)
|
|
{
|
|
unsigned long val;
|
|
unsigned char c, r, s = 0;
|
|
|
|
|
|
*res = 0;
|
|
|
|
while ((c = **str) == ' ') (*str)++; /* Skip leading spaces */
|
|
|
|
if (c == '-') { /* negative? */
|
|
s = 1;
|
|
c = *(++(*str));
|
|
}
|
|
|
|
if (c == '0') {
|
|
c = *(++(*str));
|
|
switch (c) {
|
|
case 'x': /* hexdecimal */
|
|
r = 16; c = *(++(*str));
|
|
break;
|
|
case 'b': /* binary */
|
|
r = 2; c = *(++(*str));
|
|
break;
|
|
default:
|
|
if (c <= ' ') return 1; /* single zero */
|
|
if (c < '0' || c > '9') return 0; /* invalid char */
|
|
r = 8; /* octal */
|
|
}
|
|
} else {
|
|
if (c < '0' || c > '9') return 0; /* EOL or invalid char */
|
|
r = 10; /* decimal */
|
|
}
|
|
|
|
val = 0;
|
|
while (c > ' ') {
|
|
if (c >= 'a') c -= 0x20;
|
|
c -= '0';
|
|
if (c >= 17) {
|
|
c -= 7;
|
|
if (c <= 9) return 0; /* invalid char */
|
|
}
|
|
if (c >= r) return 0; /* invalid char for current radix */
|
|
val = val * r + c;
|
|
c = *(++(*str));
|
|
}
|
|
if (s) val = 0 - val; /* apply sign if needed */
|
|
|
|
*res = val;
|
|
return 1;
|
|
}
|
|
|
|
//************************* Fat FS declare related: END
|
|
|
|
uint8_t mcucsr_mirror __attribute__ ((section (".noinit")));
|
|
|
|
// This is for fast WDT disable & and save reason of reset/power-up
|
|
void get_mcusr(void) \
|
|
__attribute__((naked)) \
|
|
__attribute__((section(".init3")));
|
|
void get_mcusr(void)
|
|
{
|
|
mcucsr_mirror = MCUSR;
|
|
MCUSR = 0;
|
|
wdt_disable();
|
|
}
|
|
//***********Prologue for fast WDT disable & and save reason of reset/power-up: END
|
|
|
|
#define PRINTF_EN 1
|
|
#if PRINTF_EN
|
|
#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
|
|
//#define PRINTF(FORMAT,args...) xprintf(PSTR(FORMAT),##args)
|
|
#else
|
|
#define PRINTF(...)
|
|
#endif
|
|
/*
|
|
#define PRINTF_EN 1
|
|
#if PRINTF_EN
|
|
#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
|
|
#else
|
|
#define PRINTF(...)
|
|
#endif
|
|
*/
|
|
/*
|
|
* m1284p minimum template, with one button & one led
|
|
*/
|
|
|
|
//M644P/M1284p Users LEDS:
|
|
//LED1/PORTC.4- m644p/m1284p maxxir
|
|
#define led1_conf() DDRC |= (1<<DDC4)
|
|
#define led1_high() PORTC |= (1<<PORTC4)
|
|
#define led1_low() PORTC &= ~(1<<PORTC4)
|
|
#define led1_tgl() PORTC ^= (1<<PORTC4)
|
|
#define led1_read() (PORTC & (1<<PORTC4))
|
|
|
|
#define sw1_conf() {DDRC &= ~(1<<DDC5); PORTC |= (1<<PORTC5);}
|
|
#define sw1_read() (PINC & (1<<PINC5))
|
|
|
|
//*********Global vars
|
|
#define TICK_PER_SEC 1000UL
|
|
volatile unsigned long _millis; // for millis tick !! Overflow every ~49.7 days
|
|
|
|
//*********Program metrics
|
|
const char compile_date[] PROGMEM = __DATE__; // Mmm dd yyyy - Äàòà êîìïèëÿöèè
|
|
const char compile_time[] PROGMEM = __TIME__; // hh:mm:ss - Âðåìÿ êîìïèëÿöèè
|
|
const char str_prog_name[] PROGMEM = "\r\nAtMega1284p v1.0 FATFS LFN Chang tst 17/12/2018\r\n"; // Program name
|
|
|
|
#if defined(__AVR_ATmega128__)
|
|
const char PROGMEM str_mcu[] = "ATmega128"; //CPU is m128
|
|
#elif defined (__AVR_ATmega2560__)
|
|
const char PROGMEM str_mcu[] = "ATmega2560"; //CPU is m2560
|
|
#elif defined (__AVR_ATmega2561__)
|
|
const char PROGMEM str_mcu[] = "ATmega2561"; //CPU is m2561
|
|
#elif defined (__AVR_ATmega328P__)
|
|
const char PROGMEM str_mcu[] = "ATmega328P"; //CPU is m328p
|
|
#elif defined (__AVR_ATmega32U4__)
|
|
const char PROGMEM str_mcu[] = "ATmega32u4"; //CPU is m32u4
|
|
#elif defined (__AVR_ATmega644P__)
|
|
const char PROGMEM str_mcu[] = "ATmega644p"; //CPU is m644p
|
|
#elif defined (__AVR_ATmega1284P__)
|
|
const char PROGMEM str_mcu[] = "ATmega1284p"; //CPU is m1284p
|
|
#else
|
|
const char PROGMEM str_mcu[] = "Unknown CPU"; //CPU is unknown
|
|
#endif
|
|
|
|
|
|
//FUNC headers
|
|
static void avr_init(void);
|
|
void timer0_init(void);
|
|
static inline unsigned long millis(void);
|
|
|
|
// RAM Memory usage test
|
|
static int freeRam (void)
|
|
{
|
|
extern int __heap_start, *__brkval;
|
|
int v;
|
|
int _res = (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
|
|
return _res;
|
|
}
|
|
|
|
|
|
//******************* MILLIS ENGINE: BEGIN
|
|
//ISR (TIMER0_COMP_vect )
|
|
ISR (TIMER0_COMPA_vect)
|
|
{
|
|
static uint8_t fatfs_10ms;
|
|
// Compare match Timer0
|
|
// Here every 1ms
|
|
_millis++; // INC millis tick
|
|
// Òåñò ìèãàåì ïðè â õîäå â ïðåðûâàíèå
|
|
// 500Hz FREQ OUT
|
|
// LED_TGL;
|
|
if(++fatfs_10ms > 9 )
|
|
{
|
|
//Here every 10ms
|
|
fatfs_10ms = 0;
|
|
Timer++; /* Performance counter for this module (for FatFS test) */
|
|
disk_timerproc(); // FAT FS timing func
|
|
}
|
|
}
|
|
|
|
static inline unsigned long millis(void)
|
|
{
|
|
unsigned long i;
|
|
cli();
|
|
// Atomic tick reading
|
|
i = _millis;
|
|
sei();
|
|
return i;
|
|
}
|
|
//******************* MILLIS ENGINE: END
|
|
|
|
//***************** UART0: BEGIN
|
|
// Assign I/O stream to UART
|
|
/* define CPU frequency in Mhz here if not defined in Makefile */
|
|
//#ifndef F_CPU
|
|
//#define F_CPU 16000000UL
|
|
//#endif
|
|
|
|
/* 19200 baud */
|
|
//#define UART_BAUD_RATE 19200
|
|
//#define UART_BAUD_RATE 38400
|
|
#define UART_BAUD_RATE 115200
|
|
|
|
static int uart0_putchar(char ch,FILE *stream);
|
|
static void uart0_rx_flash(void);
|
|
|
|
static FILE uart0_stdout = FDEV_SETUP_STREAM(uart0_putchar, NULL, _FDEV_SETUP_WRITE);
|
|
//PS. stdin íå ïåðåíàçíà÷àþ, ò.ê. óäîáíåå ñ íèì ðàáîòàòü ÷åðåç uart.h - api:
|
|
|
|
/*
|
|
* Ò.å. íàïðèìåð òàê
|
|
c = uart1_getc();
|
|
if (( c & UART_NO_DATA ) == 0)
|
|
{
|
|
uart1_putc( (unsigned char)c );
|
|
}
|
|
Ïðè ýòîì ÷åêàåì ÷òî áóôåð ïðèåìà íå ïóñò è îïðîñ èäåò íåáëîêèðóþùèé (+ ðàáîòàåì ÷åðåç UART RX RINGBUFFER),
|
|
à åñëè ðàáîòàåì â ñòèëå stdin->getchar() òàì îïðîñ áëîêèðóåòñÿ ïîêà ñèìâîë íå áóäåò ïðèíÿò (ïîëëèíã)
|
|
÷åðåç UART1_RX, ò.å. íåóäîáíî.
|
|
*/
|
|
|
|
// STDOUT UART0 TX handler
|
|
static int uart0_putchar(char ch,FILE *stream)
|
|
{
|
|
uart_putc(ch);
|
|
return 0;
|
|
}
|
|
|
|
// Î÷èùàåì áóôåð ïðèåìà UART1 RX (èíîãäà íóæíî)
|
|
static void uart0_rx_flash(void)
|
|
{
|
|
// Ñ÷èòûâàåì âñå èç ring-buffer UART1 RX
|
|
unsigned int c;
|
|
do
|
|
{
|
|
c = uart_getc();
|
|
} while (( c & UART_NO_DATA ) == 0); // Check RX1 none-empty
|
|
|
|
}
|
|
//***************** UART0: END
|
|
|
|
//***************** ADC: BEGIN
|
|
|
|
#ifndef ADC_DIV
|
|
//12.5MHz or over use this ADC reference clock
|
|
#define ADC_DIV (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) //:128 ADC Prescaler
|
|
#endif
|
|
|
|
#ifndef ADC_REF
|
|
// vcc voltage ref default
|
|
#define ADC_REF (1<<REFS0)
|
|
#endif
|
|
|
|
void adc_init(void)
|
|
{
|
|
ADCSRA = 0;
|
|
ADCSRA |= (ADC_DIV); // ADC reference clock
|
|
ADMUX |= (ADC_REF); // Voltage reference
|
|
ADCSRA |= (1<<ADEN); // Turn on ADC
|
|
ADCSRA |= (1<<ADSC); // Do an initial conversion because this one is the
|
|
// slowest and to ensure that everything is up
|
|
// and running
|
|
}
|
|
|
|
uint16_t adc_read(uint8_t channel)
|
|
{
|
|
ADMUX &= 0b11100000; //Clear the older channel that was read
|
|
ADMUX |= channel; //Defines the new ADC channel to be read
|
|
ADCSRA |= (1<<ADSC); //Starts a new conversion
|
|
while(ADCSRA & (1<<ADSC)); //Wait until the conversion is done
|
|
|
|
return ADCW; //Returns the ADC value of the chosen channel
|
|
}
|
|
//***************** ADC: END
|
|
|
|
//***************** ChaN FATFS related functions: BEGIN
|
|
// ChaN get uart line function (blocking)
|
|
// ChaN get uart line function (blocking)
|
|
static void put_rc (FRESULT rc);
|
|
|
|
static
|
|
void get_line (char *buff, uint8_t len)
|
|
{
|
|
uint8_t c, i;
|
|
uint16_t CharIn;
|
|
|
|
i = 0;
|
|
for (;;) {
|
|
|
|
// Check if char exist
|
|
// Read until data in RX buffer empty
|
|
do
|
|
{
|
|
wdt_reset(); // WDT reset at least every sec
|
|
// GET UART RX Symbol
|
|
//CharIn = uart1_getc();
|
|
CharIn = uart_getc();
|
|
}
|
|
while ( CharIn & UART_NO_DATA );
|
|
|
|
c = (char)CharIn;
|
|
|
|
if (c == '\r') break; // Line END buff
|
|
if ((c == '\b') && i) // BackSpace
|
|
{
|
|
//uart1_putc('\b');
|
|
uart_putc('\b');
|
|
i--;
|
|
}
|
|
if ((c >= ' ') && (i < len - 1)) // Fill symbols in buff
|
|
{
|
|
buff[i++] = c;
|
|
//uart1_putc(c);
|
|
uart_putc(c);
|
|
}
|
|
}
|
|
buff[i] = 0;
|
|
//uart1_putc('\n');
|
|
uart_putc('\n');
|
|
}
|
|
|
|
static
|
|
void put_dump (const BYTE *buff, DWORD ofs, BYTE cnt)
|
|
{
|
|
BYTE i;
|
|
|
|
|
|
xprintf(PSTR("%08lX:"), ofs);
|
|
|
|
for(i = 0; i < cnt; i++)
|
|
xprintf(PSTR(" %02X"), buff[i]);
|
|
|
|
xputc(' ');
|
|
for(i = 0; i < cnt; i++)
|
|
xputc((buff[i] >= ' ' && buff[i] <= '~') ? buff[i] : '.');
|
|
|
|
xputc('\n');
|
|
}
|
|
|
|
static void ls_dir(char* path)
|
|
{
|
|
DIR Dir;
|
|
FILINFO _Finfo;
|
|
BYTE res;
|
|
long p1, p2;
|
|
UINT s1, s2;
|
|
//while (*ptr == ' ') ptr++;
|
|
res = f_opendir(&Dir, path);
|
|
if (res) { put_rc(res); return; }
|
|
p1 = s1 = s2 = 0;
|
|
#if _USE_LFN
|
|
//Init buffer for LFN NAME (Without this LFN NAME not visible!!)
|
|
//Also look here:
|
|
/*
|
|
* http://microsin.net/programming/file-systems/fatfs-read-dir.html
|
|
* https://electronix.ru/forum/index.php?app=forums&module=forums&controller=topic&id=122267
|
|
*/
|
|
_Finfo.lfname = Lfname;
|
|
_Finfo.lfsize = sizeof(Lfname);
|
|
#endif
|
|
|
|
for(;;) {
|
|
res = f_readdir(&Dir, &_Finfo);
|
|
if ((res != FR_OK) || !_Finfo.fname[0]) break;
|
|
if (_Finfo.fattrib & AM_DIR) {
|
|
s2++;
|
|
} else {
|
|
s1++; p1 += _Finfo.fsize;
|
|
}
|
|
PRINTF("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %s",
|
|
(_Finfo.fattrib & AM_DIR) ? 'D' : '-',
|
|
(_Finfo.fattrib & AM_RDO) ? 'R' : '-',
|
|
(_Finfo.fattrib & AM_HID) ? 'H' : '-',
|
|
(_Finfo.fattrib & AM_SYS) ? 'S' : '-',
|
|
(_Finfo.fattrib & AM_ARC) ? 'A' : '-',
|
|
(_Finfo.fdate >> 9) + 1980, (_Finfo.fdate >> 5) & 15, _Finfo.fdate & 31,
|
|
(_Finfo.ftime >> 11), (_Finfo.ftime >> 5) & 63,
|
|
_Finfo.fsize, &(_Finfo.fname[0]));
|
|
#if _USE_LFN
|
|
for (p2 = strlen(_Finfo.fname); p2 < 14; p2++)
|
|
xputc(' ');
|
|
xprintf(PSTR("%s\r\n"), Lfname);
|
|
#else
|
|
PRINTF("\r\n");
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
static
|
|
void put_rc (FRESULT rc)
|
|
{
|
|
const prog_char *p;
|
|
static const prog_char str[] =
|
|
"OK\0" "DISK_ERR\0" "INT_ERR\0" "NOT_READY\0" "NO_FILE\0" "NO_PATH\0"
|
|
"INVALID_NAME\0" "DENIED\0" "EXIST\0" "INVALID_OBJECT\0" "WRITE_PROTECTED\0"
|
|
"INVALID_DRIVE\0" "NOT_ENABLED\0" "NO_FILE_SYSTEM\0" "MKFS_ABORTED\0" "TIMEOUT\0"
|
|
"LOCKED\0" "NOT_ENOUGH_CORE\0" "TOO_MANY_OPEN_FILES\0";
|
|
FRESULT i;
|
|
|
|
for (p = str, i = 0; i != rc && pgm_read_byte_near(p); i++) {
|
|
while(pgm_read_byte_near(p++));
|
|
}
|
|
xprintf(PSTR("rc=%u FR_%S\r\n"), rc, p);
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
// Blocking receive one symbol from uart
|
|
char uart0_receive(void)
|
|
{
|
|
unsigned int c;
|
|
uint32_t wait_start = millis();
|
|
do
|
|
{
|
|
wdt_reset();
|
|
c = uart_getc();
|
|
if (( c & UART_NO_DATA ) == 0)
|
|
{
|
|
uart_putc( (unsigned char)c );
|
|
return (char)c ;
|
|
}
|
|
//After 3.5 sec waiting return with no symbol
|
|
if((millis()-wait_start) > 3500)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
while(( c & UART_NO_DATA ));
|
|
return 0;
|
|
}
|
|
|
|
void fatfs_tst(void)
|
|
{
|
|
FRESULT f_err_code;
|
|
FIL fil_obj;
|
|
char buff[128]; // Read-write buffer
|
|
//disk_initialize(0); // Init drive
|
|
//f_err_code=f_mount(0, &FATFS_Obj); //Mount Fat Fs
|
|
f_err_code=f_mount(&FatFs[0], "", 1); /* Give a work area to the default drive */
|
|
/*
|
|
* f_mount(&Fatfs, "", 1) - mount immediatly
|
|
* f_mount(&Fatfs, "", 0) - not mount (delayed mount)
|
|
*/
|
|
|
|
PRINTF (">>Try mounting SD-CARD FAT.. ");
|
|
if(f_err_code==0)
|
|
{
|
|
PRINTF ("OK\r\n");
|
|
}
|
|
else
|
|
{
|
|
PRINTF ("ERROR ");
|
|
put_rc(f_err_code);
|
|
PRINTF("\r\nReboot the Board");
|
|
while(1)
|
|
{
|
|
_delay_ms(1000);
|
|
PRINTF(".");
|
|
}
|
|
}
|
|
|
|
f_err_code=f_mkdir ("newdir"); // Create newdir
|
|
PRINTF (">>creating <newdir> ");
|
|
if(f_err_code==0)
|
|
{
|
|
PRINTF ("OK\r\n");
|
|
}
|
|
else
|
|
{
|
|
PRINTF ("ERROR ");
|
|
put_rc(f_err_code);
|
|
}
|
|
|
|
f_err_code=f_chdir ("newdir"); // Set newdir to current directore
|
|
PRINTF (">>change default dir to <newdir> ");
|
|
if(f_err_code==0)
|
|
{
|
|
PRINTF ("OK\r\n");
|
|
}
|
|
else
|
|
{
|
|
PRINTF ("ERROR ");
|
|
put_rc(f_err_code);
|
|
}
|
|
|
|
f_err_code=f_mkdir ("newdir2"); //Create newdir2 into newdir
|
|
PRINTF (">>creating <newdir2> into <newdir> ");
|
|
if(f_err_code==0)
|
|
{
|
|
PRINTF ("OK\r\n");
|
|
}
|
|
else
|
|
{
|
|
PRINTF ("ERROR ");
|
|
put_rc(f_err_code);
|
|
}
|
|
|
|
//!! Open file only once - for creating
|
|
//f_err_code=f_open(&fil_obj, "newfile.txt",FA_CREATE_NEW|FA_WRITE);
|
|
|
|
//!!Overwrite file on open
|
|
//f_err_code=f_open(&fil_obj, "newfile.txt",FA_CREATE_ALWAYS|FA_WRITE);
|
|
|
|
//!!Auto Create && Append file mode (using f_lseek..)
|
|
f_err_code=f_open(&fil_obj, "newfile.txt",FA_OPEN_ALWAYS|FA_WRITE);
|
|
/* Move to end of the file to append data */
|
|
//This need only for append
|
|
f_lseek(&fil_obj, f_size(&fil_obj));
|
|
|
|
|
|
PRINTF (">>creating(appending) <newfile.txt> into <newdir> ");
|
|
if(f_err_code==0)
|
|
{
|
|
PRINTF ("OK\r\n");
|
|
}
|
|
else
|
|
{
|
|
PRINTF ("ERROR ");
|
|
put_rc(f_err_code);
|
|
}
|
|
|
|
//!!Only if _USE_STRFUNC = 1/2 (ffconf.h)
|
|
//f_puts("creating and writing ok if you see this\r", &fil_obj); //Writing to newfile
|
|
UINT bw;
|
|
char msg[32];
|
|
sprintf_P(msg, PSTR("%S"), PSTR("It works!\r\nAnd works..\r\n"));
|
|
f_write(&fil_obj, msg, strlen(msg), &bw); /* Write data to the file */
|
|
PRINTF(">>writing data to <newfile.txt> \r\n");
|
|
|
|
f_err_code=f_close(&fil_obj); // Close newfile
|
|
PRINTF (">>closing <newfile.txt> ");
|
|
if(f_err_code==0)
|
|
{
|
|
PRINTF ("OK\r\n");
|
|
}
|
|
else
|
|
{
|
|
PRINTF ("ERROR ");
|
|
put_rc(f_err_code);
|
|
}
|
|
|
|
f_err_code=f_open(&fil_obj, "newfile.txt",FA_READ); //Open newfile for reading
|
|
PRINTF (">>open <newfile.txt> ");
|
|
if(f_err_code==0)
|
|
{
|
|
PRINTF ("OK\r\n");
|
|
}
|
|
else
|
|
{
|
|
PRINTF ("ERROR ");
|
|
put_rc(f_err_code);
|
|
}
|
|
|
|
PRINTF (">>data in <newfile.txt>:\r\n");
|
|
//!!Only if _USE_STRFUNC = 1/2 (ffconf.h)
|
|
//PRINTF ("%s", f_gets (buff,128,&fil_obj)); //Read data from newfile
|
|
UINT cb;
|
|
f_read(&fil_obj, buff, 128, &cb);
|
|
if(cb < 128)
|
|
buff[cb] = 0x0;
|
|
else
|
|
buff[127] = 0x0;
|
|
PRINTF("%s", buff);
|
|
|
|
f_err_code=f_close(&fil_obj);
|
|
PRINTF ("\r\n>>closing <newfile.txt> "); //Close newfile
|
|
if(f_err_code==0)
|
|
{
|
|
PRINTF ("OK\r\n");
|
|
}
|
|
else
|
|
{
|
|
PRINTF ("ERROR ");
|
|
put_rc(f_err_code);
|
|
}
|
|
|
|
PRINTF ("OK\r\n\r\nSD-Card <newdir> list:\r\n");
|
|
PRINTF ("===============================================\r\n");
|
|
f_chdir("/");
|
|
//ls_dir("newdir"); //Scan newdir
|
|
ls_dir("/"); //Scan root dir
|
|
PRINTF ("===============================================\r\n\r\n");
|
|
|
|
|
|
_delay_ms(100);
|
|
uart0_rx_flash();
|
|
PRINTF("\r\n>>remove <newdir2> into <newdir?> y/N \r\n");
|
|
if (uart0_receive()=='y')
|
|
{
|
|
f_chdir("newdir");
|
|
f_err_code=f_unlink ("newdir2"); // Delete newdir2
|
|
PRINTF ("\r\n>>removing <newdir2> ");
|
|
if(f_err_code==0)
|
|
{
|
|
PRINTF ("OK\r\n");
|
|
}
|
|
else
|
|
{
|
|
PRINTF ("ERROR ");
|
|
put_rc(f_err_code);
|
|
}
|
|
}
|
|
|
|
_delay_ms(100);
|
|
uart0_rx_flash();
|
|
PRINTF("\r\n>>remove <newfile.txt> into <newdir>? y/N \r\n");
|
|
|
|
if (uart0_receive()=='y')
|
|
{
|
|
f_err_code=f_unlink ("/newdir/newfile.txt"); //Delete newfile
|
|
PRINTF ("\r\n>>removing <newfile> ");
|
|
if(f_err_code==0)
|
|
{
|
|
PRINTF ("OK\r\n");
|
|
}
|
|
else
|
|
{
|
|
PRINTF ("ERROR ");
|
|
put_rc(f_err_code);
|
|
}
|
|
}
|
|
|
|
|
|
_delay_ms(100);
|
|
uart0_rx_flash();
|
|
PRINTF("\r\nFAT FS tests finished..\r\nReboot the programm? y/N \r\n");
|
|
|
|
if (uart0_receive()=='y')
|
|
{
|
|
PRINTF("\r\nReboot the Board");
|
|
while(1)
|
|
{
|
|
_delay_ms(1000);
|
|
PRINTF(".");
|
|
}
|
|
}
|
|
|
|
PRINTF("\r\n>>>Running main programm..\r\n");
|
|
//*****************FAT FS Test: END
|
|
|
|
/*
|
|
while(1)
|
|
{
|
|
wdt_reset();
|
|
}
|
|
*/
|
|
}
|
|
|
|
#if EN_FS_MONITOR
|
|
void fatfs_monitor(void)
|
|
{
|
|
char *ptr, *ptr2;
|
|
long p1, p2, p3;
|
|
BYTE res, b1, *bp;
|
|
UINT s1, s2, cnt;
|
|
DWORD ofs, sect = 0;
|
|
FATFS *fs;
|
|
|
|
// PRINT OUT FatFS cfg metrics
|
|
PRINTF("\nFatFs module test monitor for SD-CARD/MMC\n");
|
|
xputs(_USE_LFN ? PSTR("LFN Enabled") : PSTR("LFN Disabled"));
|
|
PRINTF(", Code page: %u\n", _CODE_PAGE);
|
|
PRINTF("RTC is not available.\n");
|
|
|
|
for (;;) {
|
|
xputc('>');
|
|
ptr = Line;
|
|
|
|
get_line(ptr, sizeof Line);
|
|
switch (*ptr++) {
|
|
|
|
case 'T' :
|
|
while (*ptr == ' ') ptr++;
|
|
|
|
/* Quick test space */
|
|
|
|
break;
|
|
|
|
case 'd' :
|
|
switch (*ptr++) {
|
|
case 'd' : /* dd <pd#> [<sector>] - Dump secrtor */
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
if (!xatoi(&ptr, &p2)) p2 = sect;
|
|
res = disk_read((BYTE)p1, Buff, p2, 1);
|
|
if (res) { xprintf(PSTR("rc=%d\n"), res); break; }
|
|
sect = p2 + 1;
|
|
xprintf(PSTR("Sector:%lu\n"), p2);
|
|
for (bp=Buff, ofs = 0; ofs < 0x200; bp+=16, ofs+=16)
|
|
put_dump(bp, ofs, 16);
|
|
break;
|
|
|
|
// <di0>
|
|
case 'i' : /* di <pd#> - Initialize disk */
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
xprintf(PSTR("rc=%d\n"), disk_initialize((BYTE)p1));
|
|
break;
|
|
|
|
// <ds0>
|
|
case 's' : /* ds <pd#> - Show disk status */
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
if (disk_ioctl((BYTE)p1, GET_SECTOR_COUNT, &p2) == RES_OK)
|
|
{ xprintf(PSTR("Drive size: %lu sectors\n"), p2); }
|
|
if (disk_ioctl((BYTE)p1, GET_BLOCK_SIZE, &p2) == RES_OK)
|
|
{ xprintf(PSTR("Erase block: %lu sectors\n"), p2); }
|
|
if (disk_ioctl((BYTE)p1, MMC_GET_TYPE, &b1) == RES_OK)
|
|
{ xprintf(PSTR("Card type: %u\n"), b1); }
|
|
if (disk_ioctl((BYTE)p1, MMC_GET_CSD, Buff) == RES_OK)
|
|
{ xputs(PSTR("CSD:\n")); put_dump(Buff, 0, 16); }
|
|
if (disk_ioctl((BYTE)p1, MMC_GET_CID, Buff) == RES_OK)
|
|
{ xputs(PSTR("CID:\n")); put_dump(Buff, 0, 16); }
|
|
if (disk_ioctl((BYTE)p1, MMC_GET_OCR, Buff) == RES_OK)
|
|
{ xputs(PSTR("OCR:\n")); put_dump(Buff, 0, 4); }
|
|
if (disk_ioctl((BYTE)p1, MMC_GET_SDSTAT, Buff) == RES_OK) {
|
|
xputs(PSTR("SD Status:\n"));
|
|
for (s1 = 0; s1 < 64; s1 += 16) put_dump(Buff+s1, s1, 16);
|
|
}
|
|
if (disk_ioctl((BYTE)p1, ATA_GET_MODEL, Line) == RES_OK)
|
|
{ Line[40] = '\0'; xprintf(PSTR("Model: %s\n"), Line); }
|
|
if (disk_ioctl((BYTE)p1, ATA_GET_SN, Line) == RES_OK)
|
|
{ Line[20] = '\0'; xprintf(PSTR("S/N: %s\n"), Line); }
|
|
break;
|
|
|
|
case 'c' : /* Disk ioctl */
|
|
switch (*ptr++) {
|
|
case 's' : /* dcs <pd#> - CTRL_SYNC */
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
xprintf(PSTR("rc=%d\n"), disk_ioctl((BYTE)p1, CTRL_SYNC, 0));
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 'b' :
|
|
switch (*ptr++) {
|
|
case 'd' : /* bd <addr> - Dump R/W buffer */
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
for (bp=&Buff[p1], ofs = p1, cnt = 32; cnt; cnt--, ptr+=16, ofs+=16)
|
|
put_dump(bp, ofs, 16);
|
|
break;
|
|
|
|
case 'e' : /* be <addr> [<data>] ... - Edit R/W buffer */
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
if (xatoi(&ptr, &p2)) {
|
|
do {
|
|
Buff[p1++] = (BYTE)p2;
|
|
} while (xatoi(&ptr, &p2));
|
|
break;
|
|
}
|
|
for (;;) {
|
|
xprintf(PSTR("%04X %02X-"), (WORD)p1, Buff[p1]);
|
|
get_line(Line, sizeof Line);
|
|
ptr = Line;
|
|
if (*ptr == '.') break;
|
|
if (*ptr < ' ') { p1++; continue; }
|
|
if (xatoi(&ptr, &p2))
|
|
Buff[p1++] = (BYTE)p2;
|
|
else
|
|
xputs(PSTR("???\n"));
|
|
}
|
|
break;
|
|
|
|
case 'r' : /* br <pd#> <sector> [<n>] - Read disk into R/W buffer */
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
if (!xatoi(&ptr, &p2)) break;
|
|
if (!xatoi(&ptr, &p3)) p3 = 1;
|
|
xprintf(PSTR("rc=%u\n"), disk_read((BYTE)p1, Buff, p2, p3));
|
|
break;
|
|
|
|
case 'w' : /* bw <pd#> <sector> [<n>] - Write R/W buffer into disk */
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
if (!xatoi(&ptr, &p2)) break;
|
|
if (!xatoi(&ptr, &p3)) p3 = 1;
|
|
xprintf(PSTR("rc=%u\n"), disk_write((BYTE)p1, Buff, p2, p3));
|
|
break;
|
|
|
|
case 'f' : /* bf <n> - Fill working buffer */
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
memset(Buff, (BYTE)p1, sizeof Buff);
|
|
break;
|
|
|
|
}
|
|
break;
|
|
|
|
case 'f' :
|
|
switch (*ptr++) {
|
|
|
|
//fi
|
|
case 'i' : /* fi <ld#> [<mount>]- Initialize logical drive */
|
|
if (!xatoi(&ptr, &p1) || (UINT)p1 > 9) break;
|
|
if (!xatoi(&ptr, &p2)) p2 = 0;
|
|
xsprintf(Line, PSTR("%u:"), (UINT)p1);
|
|
put_rc(f_mount(&FatFs[p1], Line, (BYTE)p2));
|
|
break;
|
|
|
|
//fs
|
|
case 's' : /* fs [<path>] - Show logical drive status */
|
|
while (*ptr == ' ') ptr++;
|
|
ptr2 = ptr;
|
|
res = f_getfree(ptr, (DWORD*)&p2, &fs);
|
|
if (res) { put_rc(res); break; }
|
|
xprintf(PSTR("FAT type = %u\nBytes/Cluster = %lu\nNumber of FATs = %u\n"
|
|
"Root DIR entries = %u\nSectors/FAT = %lu\nNumber of clusters = %lu\n"
|
|
"FAT start (lba) = %lu\nDIR start (lba,clustor) = %lu\nData start (lba) = %lu\n\n"),
|
|
fs->fs_type, (DWORD)fs->csize * 512, fs->n_fats,
|
|
fs->n_rootdir, fs->fsize, fs->n_fatent - 2,
|
|
fs->fatbase, fs->dirbase, fs->database
|
|
);
|
|
#if _USE_LABEL
|
|
res = f_getlabel(ptr2, (char*)Buff, (DWORD*)&p1);
|
|
if (res) { put_rc(res); break; }
|
|
xprintf(Buff[0] ? PSTR("Volume name is %s\n") : PSTR("No volume label\n"), Buff);
|
|
xprintf(PSTR("Volume S/N is %04X-%04X\n"), (WORD)((DWORD)p1 >> 16), (WORD)(p1 & 0xFFFF));
|
|
#endif
|
|
xputs(PSTR("..."));
|
|
AccSize = AccFiles = AccDirs = 0;
|
|
strcpy((char*)Buff, ptr);
|
|
res = scan_files((char*)Buff);
|
|
if (res) { put_rc(res); break; }
|
|
xprintf(PSTR("\r%u files, %lu bytes.\n%u folders.\n"
|
|
"%lu KB total disk space.\n%lu KB available.\n"),
|
|
AccFiles, AccSize, AccDirs,
|
|
(fs->n_fatent - 2) * (fs->csize / 2), p2 * (fs->csize / 2)
|
|
);
|
|
break;
|
|
|
|
//fl
|
|
case 'l' : /* fl [<path>] - Directory listing */
|
|
while (*ptr == ' ') ptr++;
|
|
res = f_opendir(&Dir, ptr);
|
|
if (res) { put_rc(res); break; }
|
|
p1 = s1 = s2 = 0;
|
|
for(;;) {
|
|
res = f_readdir(&Dir, &Finfo);
|
|
if ((res != FR_OK) || !Finfo.fname[0]) break;
|
|
if (Finfo.fattrib & AM_DIR) {
|
|
s2++;
|
|
} else {
|
|
s1++; p1 += Finfo.fsize;
|
|
}
|
|
xprintf(PSTR("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %s"),
|
|
(Finfo.fattrib & AM_DIR) ? 'D' : '-',
|
|
(Finfo.fattrib & AM_RDO) ? 'R' : '-',
|
|
(Finfo.fattrib & AM_HID) ? 'H' : '-',
|
|
(Finfo.fattrib & AM_SYS) ? 'S' : '-',
|
|
(Finfo.fattrib & AM_ARC) ? 'A' : '-',
|
|
(Finfo.fdate >> 9) + 1980, (Finfo.fdate >> 5) & 15, Finfo.fdate & 31,
|
|
(Finfo.ftime >> 11), (Finfo.ftime >> 5) & 63,
|
|
Finfo.fsize, &(Finfo.fname[0]));
|
|
#if _USE_LFN
|
|
for (p2 = strlen(Finfo.fname); p2 < 14; p2++)
|
|
xputc(' ');
|
|
xprintf(PSTR("%s\n"), Lfname);
|
|
#else
|
|
xputc('\n');
|
|
#endif
|
|
}
|
|
if (res == FR_OK) {
|
|
xprintf(PSTR("%4u File(s),%10lu bytes total\n%4u Dir(s)"), s1, p1, s2);
|
|
if (f_getfree(ptr, (DWORD*)&p1, &fs) == FR_OK)
|
|
xprintf(PSTR(", %10luK bytes free\n"), p1 * fs->csize / 2);
|
|
}
|
|
if (res) put_rc(res);
|
|
break;
|
|
|
|
// <fo 0x1 123.txt> - Îòêðûâàåì äëÿ ÷òåíèÿ(FA_OPEN_READ = 0x1) ôàéë "123.txt"
|
|
case 'o' : /* fo <mode> <name> - Open a file */
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
while (*ptr == ' ') ptr++;
|
|
put_rc(f_open(&File[0], ptr, (BYTE)p1));
|
|
break;
|
|
|
|
case 'c' : /* fc - Close a file */
|
|
put_rc(f_close(&File[0]));
|
|
break;
|
|
|
|
case 'e' : /* fe - Seek file pointer */
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
res = f_lseek(&File[0], p1);
|
|
put_rc(res);
|
|
if (res == FR_OK)
|
|
xprintf(PSTR("fptr = %lu(0x%lX)\n"), File[0].fptr, File[0].fptr);
|
|
break;
|
|
|
|
case 'r' : /* fr <len> - read file */
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
p2 = 0;
|
|
cli(); Timer = 0; sei();
|
|
while (p1) {
|
|
if (p1 >= sizeof Buff) { cnt = sizeof Buff; p1 -= sizeof Buff; }
|
|
else { cnt = (WORD)p1; p1 = 0; }
|
|
res = f_read(&File[0], Buff, cnt, &s2);
|
|
if (res != FR_OK) { put_rc(res); break; }
|
|
p2 += s2;
|
|
if (cnt != s2) break;
|
|
}
|
|
cli(); s2 = Timer; sei();
|
|
xprintf(PSTR("%lu bytes read with %lu bytes/sec.\n"), p2, s2 ? (p2 * 100 / s2) : 0);
|
|
break;
|
|
|
|
case 'd' : /* fd <len> - read and dump file from current fp */
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
ofs = File[0].fptr;
|
|
while (p1) {
|
|
if (p1 >= 16) { cnt = 16; p1 -= 16; }
|
|
else { cnt = (WORD)p1; p1 = 0; }
|
|
res = f_read(&File[0], Buff, cnt, &cnt);
|
|
if (res != FR_OK) { put_rc(res); break; }
|
|
if (!cnt) break;
|
|
put_dump(Buff, ofs, cnt);
|
|
ofs += 16;
|
|
}
|
|
break;
|
|
|
|
case 'w' : /* fw <len> <val> - write file */
|
|
if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2)) break;
|
|
memset(Buff, (BYTE)p2, sizeof Buff);
|
|
p2 = 0;
|
|
cli(); Timer = 0; sei();
|
|
while (p1) {
|
|
if (p1 >= sizeof Buff) { cnt = sizeof Buff; p1 -= sizeof Buff; }
|
|
else { cnt = (WORD)p1; p1 = 0; }
|
|
res = f_write(&File[0], Buff, cnt, &s2);
|
|
if (res != FR_OK) { put_rc(res); break; }
|
|
p2 += s2;
|
|
if (cnt != s2) break;
|
|
}
|
|
cli(); s2 = Timer; sei();
|
|
xprintf(PSTR("%lu bytes written with %lu bytes/sec.\n"), p2, s2 ? (p2 * 100 / s2) : 0);
|
|
break;
|
|
|
|
case 'v' : /* fv - Truncate file */
|
|
put_rc(f_truncate(&File[0]));
|
|
break;
|
|
|
|
case 'n' : /* fn <old_name> <new_name> - Change file/dir name */
|
|
while (*ptr == ' ') ptr++;
|
|
ptr2 = strchr(ptr, ' ');
|
|
if (!ptr2) break;
|
|
*ptr2++ = 0;
|
|
while (*ptr2 == ' ') ptr2++;
|
|
put_rc(f_rename(ptr, ptr2));
|
|
break;
|
|
|
|
case 'u' : /* fu <name> - Unlink a file or dir */
|
|
while (*ptr == ' ') ptr++;
|
|
put_rc(f_unlink(ptr));
|
|
break;
|
|
|
|
case 'k' : /* fk <name> - Create a directory */
|
|
while (*ptr == ' ') ptr++;
|
|
put_rc(f_mkdir(ptr));
|
|
break;
|
|
|
|
case 'a' : /* fa <atrr> <mask> <name> - Change file/dir attribute */
|
|
if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2)) break;
|
|
while (*ptr == ' ') ptr++;
|
|
put_rc(f_chmod(ptr, p1, p2));
|
|
break;
|
|
|
|
case 't' : /* ft <year> <month> <day> <hour> <min> <sec> <name> */
|
|
if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) break;
|
|
Finfo.fdate = ((p1 - 1980) << 9) | ((p2 & 15) << 5) | (p3 & 31);
|
|
if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) break;
|
|
Finfo.ftime = ((p1 & 31) << 11) | ((p2 & 63) << 5) | ((p3 >> 1) & 31);
|
|
while (*ptr == ' ') ptr++;
|
|
put_rc(f_utime(ptr, &Finfo));
|
|
break;
|
|
|
|
case 'x' : /* fx <src_name> <dst_name> - Copy file */
|
|
while (*ptr == ' ') ptr++;
|
|
ptr2 = strchr(ptr, ' ');
|
|
if (!ptr2) break;
|
|
*ptr2++ = 0;
|
|
while (*ptr2 == ' ') ptr2++;
|
|
xprintf(PSTR("Opening \"%s\""), ptr);
|
|
res = f_open(&File[0], ptr, FA_OPEN_EXISTING | FA_READ);
|
|
if (res) {
|
|
put_rc(res);
|
|
break;
|
|
}
|
|
xprintf(PSTR("\nCreating \"%s\""), ptr2);
|
|
res = f_open(&File[1], ptr2, FA_CREATE_ALWAYS | FA_WRITE);
|
|
if (res) {
|
|
put_rc(res);
|
|
f_close(&File[0]);
|
|
break;
|
|
}
|
|
xprintf(PSTR("\nCopying..."));
|
|
cli(); Timer = 0; sei();
|
|
p1 = 0;
|
|
for (;;) {
|
|
res = f_read(&File[0], Buff, sizeof Buff, &s1);
|
|
if (res || s1 == 0) break; /* error or eof */
|
|
res = f_write(&File[1], Buff, s1, &s2);
|
|
p1 += s2;
|
|
if (res || s2 < s1) break; /* error or disk full */
|
|
}
|
|
if (res) put_rc(res);
|
|
cli(); s2 = Timer; sei();
|
|
xprintf(PSTR("\n%lu bytes copied with %lu bytes/sec.\n"), p1, p1 * 100 / s2);
|
|
f_close(&File[0]);
|
|
f_close(&File[1]);
|
|
break;
|
|
#if _FS_RPATH
|
|
case 'g' : /* fg <path> - Change current directory */
|
|
while (*ptr == ' ') ptr++;
|
|
put_rc(f_chdir(ptr));
|
|
break;
|
|
#if _VOLUMES >= 2
|
|
case 'j' : /* fj <path> - Change current drive */
|
|
while (*ptr == ' ') ptr++;
|
|
put_rc(f_chdrive(ptr));
|
|
break;
|
|
#endif
|
|
#if _FS_RPATH >= 2
|
|
case 'q' : /* fq - Show current dir path */
|
|
res = f_getcwd(Line, sizeof Line);
|
|
if (res)
|
|
put_rc(res);
|
|
else
|
|
xprintf(PSTR("%s\n"), Line);
|
|
break;
|
|
#endif
|
|
#endif
|
|
#if _USE_LABEL
|
|
case 'b' : /* fb <name> - Set volume label */
|
|
while (*ptr == ' ') ptr++;
|
|
put_rc(f_setlabel(ptr));
|
|
break;
|
|
#endif
|
|
#if _USE_MKFS
|
|
case 'm' : /* fm <ld#> <part type> <bytes/clust> - Create file system */
|
|
if (!xatoi(&ptr, &p1) || (UINT)p1 > 9 || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) break;
|
|
xprintf(PSTR("The drive %u will be formatted. Are you sure? (Y/n)="), (WORD)p1);
|
|
get_line(Line, sizeof Line);
|
|
if (*ptr == 'Y') {
|
|
xsprintf(Line, PSTR("%u:"), (UINT)p1);
|
|
put_rc(f_mkfs(Line, (BYTE)p2, (WORD)p3));
|
|
}
|
|
break;
|
|
#endif
|
|
}
|
|
break;
|
|
#ifdef SOUND_DEFINED
|
|
case 'p' : /* p <wavfile> - Play RIFF-WAV file (upto data rate of 48kB/sec) */
|
|
while (*ptr == ' ') ptr++;
|
|
res = f_open(&File[0], ptr, FA_READ);
|
|
if (res) {
|
|
put_rc(res);
|
|
} else {
|
|
load_wav(&File[0], "**** WAV PLAYER ****", Buff, sizeof Buff);
|
|
f_close(&File[0]);
|
|
}
|
|
break;
|
|
#endif
|
|
//!! RTC not released yet
|
|
/*
|
|
case 't' : // t [<year> <mon> <mday> <hour> <min> <sec>]
|
|
if (!RtcOk) break;
|
|
if (xatoi(&ptr, &p1)) {
|
|
rtc.year = (WORD)p1;
|
|
xatoi(&ptr, &p1); rtc.month = (BYTE)p1;
|
|
xatoi(&ptr, &p1); rtc.mday = (BYTE)p1;
|
|
xatoi(&ptr, &p1); rtc.hour = (BYTE)p1;
|
|
xatoi(&ptr, &p1); rtc.min = (BYTE)p1;
|
|
if (!xatoi(&ptr, &p1)) break;
|
|
rtc.sec = (BYTE)p1;
|
|
rtc_settime(&rtc);
|
|
}
|
|
rtc_gettime(&rtc);
|
|
xprintf(PSTR("%u/%u/%u %02u:%02u:%02u\n"), rtc.year, rtc.month, rtc.mday, rtc.hour, rtc.min, rtc.sec);
|
|
break;
|
|
*/
|
|
case '?' : /* Show Command List */
|
|
xputs(PSTR(
|
|
"[Disk contorls]\n"
|
|
" di <pd#> - Initialize disk\n"
|
|
" dd [<pd#> <sect>] - Dump a secrtor\n"
|
|
" ds <pd#> - Show disk status\n"
|
|
" dcs <pd#> - ioctl(CTRL_SYNC)\n"
|
|
"[Buffer controls]\n"
|
|
" bd <ofs> - Dump working buffer\n"
|
|
" be <ofs> [<data>] ... - Edit working buffer\n"
|
|
" br <pd#> <sect> [<num>] - Read disk into working buffer\n"
|
|
" bw <pd#> <sect> [<num>] - Write working buffer into disk\n"
|
|
" bf <val> - Fill working buffer\n"
|
|
"[File system controls]\n"
|
|
" fi <ld#> [<mount>] - Force initialized the volume\n"
|
|
" fs [<path>] - Show volume status\n"
|
|
" fl [<path>] - Show a directory\n"
|
|
" fo <mode> <file> - Open a file\n"
|
|
" fc - Close the file\n"
|
|
" fe <ofs> - Move fp in normal seek\n"
|
|
" fd <len> - Read and dump the file\n"
|
|
" fr <len> - Read the file\n"
|
|
" fw <len> <val> - Write to the file\n"
|
|
" fn <org name> <new name> - Rename an object\n"
|
|
" fu <obj name> - Unlink an object\n"
|
|
" fv - Truncate the file at current fp\n"
|
|
" fk <dir name> - Create a directory\n"
|
|
" fa <atrr> <mask> <object name> - Change object attribute\n"
|
|
" ft <year> <month> <day> <hour> <min> <sec> <object name> - Change timestamp of an object\n"
|
|
" fx <src file> <dst file> - Copy a file\n"
|
|
" fg <path> - Change current directory\n"
|
|
" fj <path> - Change current drive\n"
|
|
" fq - Show current directory\n"
|
|
" fm <ld#> <rule> <cluster size> - Create file system\n"
|
|
"[Misc commands]\n"
|
|
" p <wavfile> - Play RIFF-WAVE file\n"
|
|
" t [<year> <month> <mday> <hour> <min> <sec>] - Set/Show current time\n"
|
|
"\n"));
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
//***************** ChaN FATFS related functions: END
|
|
|
|
|
|
int main()
|
|
{
|
|
uint8_t prev_sw1 = 1; // VAR for sw1 pressing detect
|
|
|
|
// INIT MCU
|
|
avr_init();
|
|
|
|
// Print program metrics
|
|
PRINTF("%S", str_prog_name);// Íàçâàíèå ïðîãðàììû
|
|
PRINTF("Compiled at: %S %S\r\n", compile_time, compile_date);// Âðåìÿ Äàòà êîìïèëÿöèè
|
|
PRINTF(">> MCU is: %S; CLK is: %luHz\r\n", str_mcu, F_CPU);// MCU Name && FREQ
|
|
PRINTF(">> Free RAM is: %d bytes\r\n", freeRam());
|
|
|
|
//Short Blink LED 3 times on startup
|
|
unsigned char i = 3;
|
|
while(i--)
|
|
{
|
|
led1_high();
|
|
_delay_ms(100);
|
|
led1_low();
|
|
_delay_ms(400);
|
|
wdt_reset();
|
|
}
|
|
|
|
fatfs_tst(); //Quick self-test FATFS
|
|
#if EN_FS_MONITOR
|
|
fatfs_monitor(); //FATFS monitor terminal
|
|
#endif
|
|
while(1)
|
|
{
|
|
;
|
|
}
|
|
|
|
unsigned long prev_millis = 0;
|
|
unsigned long rx_millis = 0;
|
|
unsigned long uptime = 0;
|
|
uint16_t CharIn;
|
|
while(1)
|
|
{
|
|
//Here at least every 1sec
|
|
wdt_reset(); // WDT reset at least every sec
|
|
if((millis()-prev_millis)>TICK_PER_SEC)
|
|
{
|
|
//Here every 1sec
|
|
wdt_reset(); // WDT reset at least every sec
|
|
prev_millis = millis();
|
|
led1_tgl();
|
|
PRINTF("Uptime %lu sec\r\n", uptime++);
|
|
//PRINTF("ADC5: %d\r\n", adc_read(5));
|
|
|
|
|
|
//!! SW1 pressing action
|
|
if(!sw1_read())// Check for SW1 pressed every second
|
|
{
|
|
// SW1 is pressed
|
|
//led1_high(); //LED1 ON
|
|
if(prev_sw1)
|
|
{
|
|
//!! Çäåñü ïî ôàêòó íàæàòèÿ êíîïêè (1->0 SW1)
|
|
//!! Debug only
|
|
PRINTF("SW1 is pressed\r\nADC0/PA0 is: %u\r\n", adc_read(0));
|
|
//PRINTF("SW1 is pressed\r\n");
|
|
}//if(prev_sw1)
|
|
prev_sw1 = 0; // Store SW1 state for next iteration
|
|
}//if(!sw1_read())
|
|
else
|
|
{
|
|
// SW1 is unpressed
|
|
//led1_low(); // LED1 OFF
|
|
prev_sw1 = 1;// Store SW1 state for next iteration
|
|
}//if(!sw1_read())else..
|
|
}//if((millis()-prev_millis)>TICK_PER_SEC)
|
|
|
|
if((millis()-rx_millis)>0)
|
|
{
|
|
// Here every 1 msec, to check UART RX
|
|
rx_millis = millis();
|
|
|
|
// GET UART RX Symbol
|
|
CharIn = uart_getc();
|
|
|
|
// Check if char exist
|
|
// Read until data in RX buffer present
|
|
while (( CharIn & UART_NO_DATA ) == 0)
|
|
{
|
|
wdt_reset(); // WDT reset at least every sec
|
|
//!! Debug only
|
|
//Read data from UART0 RX ring buffer & send back echo
|
|
uart_putc(CharIn+1);
|
|
// GET UART RX Symbol
|
|
CharIn = uart_getc();
|
|
}
|
|
}//if((millis()-rx_millis)>0)
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Timer0
|
|
// 1ms IRQ
|
|
// Used for millis() timing
|
|
void timer0_init(void)
|
|
{
|
|
/*
|
|
*
|
|
* For M128
|
|
TCCR0 = (1<<CS02)|(1<<WGM01); //TIMER0 SET-UP: CTC MODE & PS 1:64
|
|
OCR0 = 249; // 1ms reach for clear (16mz:64=>250kHz:250-=>1kHz)
|
|
TIMSK |= 1<<OCIE0; //IRQ on TIMER0 output compare
|
|
*/
|
|
//For M664p
|
|
TCCR0A = (1<<WGM01); //TIMER0 SET-UP: CTC MODE
|
|
TCCR0B = (1<<CS01)|(1<<CS00); // PS 1:64
|
|
OCR0A = 249; // 1ms reach for clear (16mz:64=>250kHz:250-=>1kHz)
|
|
TIMSK0 |= 1<<OCIE0A; //IRQ on TIMER0 output compareA
|
|
}
|
|
|
|
static void avr_init(void)
|
|
{
|
|
// Initialize device here.
|
|
// WatchDog INIT
|
|
wdt_enable(WDTO_8S); // set up wdt reset interval 2 second
|
|
wdt_reset(); // wdt reset ~ every <2000ms
|
|
|
|
timer0_init();// Timer0 millis engine init
|
|
|
|
// Initial UART Peripheral
|
|
/*
|
|
* Initialize uart11 library, pass baudrate and AVR cpu clock
|
|
* with the macro
|
|
* uart1_BAUD_SELECT() (normal speed mode )
|
|
* or
|
|
* uart1_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode)
|
|
*/
|
|
#if (UART_BAUD_RATE == 115200)
|
|
uart_init( UART_BAUD_SELECT_DOUBLE_SPEED(UART_BAUD_RATE,F_CPU) ); // To works without error on 115200 bps/F_CPU=16Mhz
|
|
#else
|
|
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
|
|
#endif
|
|
// Define Output/Input Stream
|
|
stdout = &uart0_stdout;
|
|
|
|
// Redirect to <xitoa> Chan lib
|
|
// Should not used here, because Chan xprintf redirect via stdout
|
|
//xfunc_out = uart1_putc;
|
|
//xfunc_out = uart_putc;
|
|
|
|
//ADC init
|
|
adc_init();
|
|
adc_read(0); //Dummy read
|
|
|
|
|
|
led1_conf();
|
|
led1_low();// LED1 is OFF
|
|
|
|
|
|
sw1_conf();//SW1 internal pull-up
|
|
|
|
sei(); //re-enable global interrupts
|
|
|
|
return;
|
|
}
|
|
|