Browse Source
* Fix mistake in gitignore file and add in missing core files. The missing leading slash on "lib" meant all folders names lib in the directory tree are ignored, rather than just the top level PlatformIO lib folder * Add LiquidCrystal Library and associated headers modified to compile.pull/1/head
Chris Pepper
7 years ago
committed by
Scott Lahteine
35 changed files with 30689 additions and 1 deletions
@ -0,0 +1,326 @@ |
|||
#include "LiquidCrystal.h" |
|||
|
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
#include <inttypes.h> |
|||
#include "../../../../src/HAL/HAL_LPC1768/arduino.h" |
|||
|
|||
// When the display powers up, it is configured as follows:
|
|||
//
|
|||
// 1. Display clear
|
|||
// 2. Function set:
|
|||
// DL = 1; 8-bit interface data
|
|||
// N = 0; 1-line display
|
|||
// F = 0; 5x8 dot character font
|
|||
// 3. Display on/off control:
|
|||
// D = 0; Display off
|
|||
// C = 0; Cursor off
|
|||
// B = 0; Blinking off
|
|||
// 4. Entry mode set:
|
|||
// I/D = 1; Increment by 1
|
|||
// S = 0; No shift
|
|||
//
|
|||
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
|
|||
// can't assume that its in that state when a sketch starts (and the
|
|||
// LiquidCrystal constructor is called).
|
|||
|
|||
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, |
|||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, |
|||
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) |
|||
{ |
|||
init(0, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7); |
|||
} |
|||
|
|||
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, |
|||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, |
|||
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) |
|||
{ |
|||
init(0, rs, 255, enable, d0, d1, d2, d3, d4, d5, d6, d7); |
|||
} |
|||
|
|||
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, |
|||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) |
|||
{ |
|||
init(1, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0); |
|||
} |
|||
|
|||
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, |
|||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) |
|||
{ |
|||
init(1, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0); |
|||
} |
|||
|
|||
void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable, |
|||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, |
|||
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) |
|||
{ |
|||
_rs_pin = rs; |
|||
_rw_pin = rw; |
|||
_enable_pin = enable; |
|||
|
|||
_data_pins[0] = d0; |
|||
_data_pins[1] = d1; |
|||
_data_pins[2] = d2; |
|||
_data_pins[3] = d3; |
|||
_data_pins[4] = d4; |
|||
_data_pins[5] = d5; |
|||
_data_pins[6] = d6; |
|||
_data_pins[7] = d7; |
|||
|
|||
if (fourbitmode) |
|||
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; |
|||
else |
|||
_displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS; |
|||
|
|||
begin(16, 1); |
|||
} |
|||
|
|||
void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { |
|||
if (lines > 1) { |
|||
_displayfunction |= LCD_2LINE; |
|||
} |
|||
_numlines = lines; |
|||
|
|||
setRowOffsets(0x00, 0x40, 0x00 + cols, 0x40 + cols); |
|||
|
|||
// for some 1 line displays you can select a 10 pixel high font
|
|||
if ((dotsize != LCD_5x8DOTS) && (lines == 1)) { |
|||
_displayfunction |= LCD_5x10DOTS; |
|||
} |
|||
|
|||
pinMode(_rs_pin, OUTPUT); |
|||
// we can save 1 pin by not using RW. Indicate by passing 255 instead of pin#
|
|||
if (_rw_pin != 255) { |
|||
pinMode(_rw_pin, OUTPUT); |
|||
} |
|||
pinMode(_enable_pin, OUTPUT); |
|||
|
|||
// Do these once, instead of every time a character is drawn for speed reasons.
|
|||
for (int i=0; i<((_displayfunction & LCD_8BITMODE) ? 8 : 4); ++i) |
|||
{ |
|||
pinMode(_data_pins[i], OUTPUT); |
|||
} |
|||
|
|||
// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
|
|||
// according to datasheet, we need at least 40ms after power rises above 2.7V
|
|||
// before sending commands. Arduino can turn on way before 4.5V so we'll wait 50
|
|||
delayMicroseconds(50000); |
|||
// Now we pull both RS and R/W low to begin commands
|
|||
digitalWrite(_rs_pin, LOW); |
|||
digitalWrite(_enable_pin, LOW); |
|||
if (_rw_pin != 255) { |
|||
digitalWrite(_rw_pin, LOW); |
|||
} |
|||
|
|||
//put the LCD into 4 bit or 8 bit mode
|
|||
if (! (_displayfunction & LCD_8BITMODE)) { |
|||
// this is according to the hitachi HD44780 datasheet
|
|||
// figure 24, pg 46
|
|||
|
|||
// we start in 8bit mode, try to set 4 bit mode
|
|||
write4bits(0x03); |
|||
delayMicroseconds(4500); // wait min 4.1ms
|
|||
|
|||
// second try
|
|||
write4bits(0x03); |
|||
delayMicroseconds(4500); // wait min 4.1ms
|
|||
|
|||
// third go!
|
|||
write4bits(0x03); |
|||
delayMicroseconds(150); |
|||
|
|||
// finally, set to 4-bit interface
|
|||
write4bits(0x02); |
|||
} else { |
|||
// this is according to the hitachi HD44780 datasheet
|
|||
// page 45 figure 23
|
|||
|
|||
// Send function set command sequence
|
|||
command(LCD_FUNCTIONSET | _displayfunction); |
|||
delayMicroseconds(4500); // wait more than 4.1ms
|
|||
|
|||
// second try
|
|||
command(LCD_FUNCTIONSET | _displayfunction); |
|||
delayMicroseconds(150); |
|||
|
|||
// third go
|
|||
command(LCD_FUNCTIONSET | _displayfunction); |
|||
} |
|||
|
|||
// finally, set # lines, font size, etc.
|
|||
command(LCD_FUNCTIONSET | _displayfunction); |
|||
|
|||
// turn the display on with no cursor or blinking default
|
|||
_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; |
|||
display(); |
|||
|
|||
// clear it off
|
|||
clear(); |
|||
|
|||
// Initialize to default text direction (for romance languages)
|
|||
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; |
|||
// set the entry mode
|
|||
command(LCD_ENTRYMODESET | _displaymode); |
|||
|
|||
} |
|||
|
|||
void LiquidCrystal::setRowOffsets(int row0, int row1, int row2, int row3) |
|||
{ |
|||
_row_offsets[0] = row0; |
|||
_row_offsets[1] = row1; |
|||
_row_offsets[2] = row2; |
|||
_row_offsets[3] = row3; |
|||
} |
|||
|
|||
/********** high level commands, for the user! */ |
|||
void LiquidCrystal::clear() |
|||
{ |
|||
command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
|||
delayMicroseconds(2000); // this command takes a long time!
|
|||
} |
|||
|
|||
void LiquidCrystal::home() |
|||
{ |
|||
command(LCD_RETURNHOME); // set cursor position to zero
|
|||
delayMicroseconds(2000); // this command takes a long time!
|
|||
} |
|||
|
|||
void LiquidCrystal::setCursor(uint8_t col, uint8_t row) |
|||
{ |
|||
const size_t max_lines = sizeof(_row_offsets) / sizeof(*_row_offsets); |
|||
if ( row >= max_lines ) { |
|||
row = max_lines - 1; // we count rows starting w/0
|
|||
} |
|||
if ( row >= _numlines ) { |
|||
row = _numlines - 1; // we count rows starting w/0
|
|||
} |
|||
|
|||
command(LCD_SETDDRAMADDR | (col + _row_offsets[row])); |
|||
} |
|||
|
|||
// Turn the display on/off (quickly)
|
|||
void LiquidCrystal::noDisplay() { |
|||
_displaycontrol &= ~LCD_DISPLAYON; |
|||
command(LCD_DISPLAYCONTROL | _displaycontrol); |
|||
} |
|||
void LiquidCrystal::display() { |
|||
_displaycontrol |= LCD_DISPLAYON; |
|||
command(LCD_DISPLAYCONTROL | _displaycontrol); |
|||
} |
|||
|
|||
// Turns the underline cursor on/off
|
|||
void LiquidCrystal::noCursor() { |
|||
_displaycontrol &= ~LCD_CURSORON; |
|||
command(LCD_DISPLAYCONTROL | _displaycontrol); |
|||
} |
|||
void LiquidCrystal::cursor() { |
|||
_displaycontrol |= LCD_CURSORON; |
|||
command(LCD_DISPLAYCONTROL | _displaycontrol); |
|||
} |
|||
|
|||
// Turn on and off the blinking cursor
|
|||
void LiquidCrystal::noBlink() { |
|||
_displaycontrol &= ~LCD_BLINKON; |
|||
command(LCD_DISPLAYCONTROL | _displaycontrol); |
|||
} |
|||
void LiquidCrystal::blink() { |
|||
_displaycontrol |= LCD_BLINKON; |
|||
command(LCD_DISPLAYCONTROL | _displaycontrol); |
|||
} |
|||
|
|||
// These commands scroll the display without changing the RAM
|
|||
void LiquidCrystal::scrollDisplayLeft(void) { |
|||
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); |
|||
} |
|||
void LiquidCrystal::scrollDisplayRight(void) { |
|||
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); |
|||
} |
|||
|
|||
// This is for text that flows Left to Right
|
|||
void LiquidCrystal::leftToRight(void) { |
|||
_displaymode |= LCD_ENTRYLEFT; |
|||
command(LCD_ENTRYMODESET | _displaymode); |
|||
} |
|||
|
|||
// This is for text that flows Right to Left
|
|||
void LiquidCrystal::rightToLeft(void) { |
|||
_displaymode &= ~LCD_ENTRYLEFT; |
|||
command(LCD_ENTRYMODESET | _displaymode); |
|||
} |
|||
|
|||
// This will 'right justify' text from the cursor
|
|||
void LiquidCrystal::autoscroll(void) { |
|||
_displaymode |= LCD_ENTRYSHIFTINCREMENT; |
|||
command(LCD_ENTRYMODESET | _displaymode); |
|||
} |
|||
|
|||
// This will 'left justify' text from the cursor
|
|||
void LiquidCrystal::noAutoscroll(void) { |
|||
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT; |
|||
command(LCD_ENTRYMODESET | _displaymode); |
|||
} |
|||
|
|||
// Allows us to fill the first 8 CGRAM locations
|
|||
// with custom characters
|
|||
void LiquidCrystal::createChar(uint8_t location, uint8_t charmap[]) { |
|||
location &= 0x7; // we only have 8 locations 0-7
|
|||
command(LCD_SETCGRAMADDR | (location << 3)); |
|||
for (int i=0; i<8; i++) { |
|||
write(charmap[i]); |
|||
} |
|||
} |
|||
|
|||
/*********** mid level commands, for sending data/cmds */ |
|||
|
|||
inline void LiquidCrystal::command(uint8_t value) { |
|||
send(value, LOW); |
|||
} |
|||
|
|||
inline size_t LiquidCrystal::write(uint8_t value) { |
|||
send(value, HIGH); |
|||
return 1; // assume sucess
|
|||
} |
|||
|
|||
/************ low level data pushing commands **********/ |
|||
|
|||
// write either command or data, with automatic 4/8-bit selection
|
|||
void LiquidCrystal::send(uint8_t value, uint8_t mode) { |
|||
digitalWrite(_rs_pin, mode); |
|||
|
|||
// if there is a RW pin indicated, set it low to Write
|
|||
if (_rw_pin != 255) { |
|||
digitalWrite(_rw_pin, LOW); |
|||
} |
|||
|
|||
if (_displayfunction & LCD_8BITMODE) { |
|||
write8bits(value); |
|||
} else { |
|||
write4bits(value>>4); |
|||
write4bits(value); |
|||
} |
|||
} |
|||
|
|||
void LiquidCrystal::pulseEnable(void) { |
|||
digitalWrite(_enable_pin, LOW); |
|||
delayMicroseconds(1); |
|||
digitalWrite(_enable_pin, HIGH); |
|||
delayMicroseconds(1); // enable pulse must be >450ns
|
|||
digitalWrite(_enable_pin, LOW); |
|||
delayMicroseconds(100); // commands need > 37us to settle
|
|||
} |
|||
|
|||
void LiquidCrystal::write4bits(uint8_t value) { |
|||
for (int i = 0; i < 4; i++) { |
|||
digitalWrite(_data_pins[i], (value >> i) & 0x01); |
|||
} |
|||
|
|||
pulseEnable(); |
|||
} |
|||
|
|||
void LiquidCrystal::write8bits(uint8_t value) { |
|||
for (int i = 0; i < 8; i++) { |
|||
digitalWrite(_data_pins[i], (value >> i) & 0x01); |
|||
} |
|||
|
|||
pulseEnable(); |
|||
} |
@ -0,0 +1,109 @@ |
|||
#ifndef LiquidCrystal_h |
|||
#define LiquidCrystal_h |
|||
|
|||
#include <inttypes.h> |
|||
#include "binary.h" |
|||
#include "Print.h" |
|||
|
|||
// commands
|
|||
#define LCD_CLEARDISPLAY 0x01 |
|||
#define LCD_RETURNHOME 0x02 |
|||
#define LCD_ENTRYMODESET 0x04 |
|||
#define LCD_DISPLAYCONTROL 0x08 |
|||
#define LCD_CURSORSHIFT 0x10 |
|||
#define LCD_FUNCTIONSET 0x20 |
|||
#define LCD_SETCGRAMADDR 0x40 |
|||
#define LCD_SETDDRAMADDR 0x80 |
|||
|
|||
// flags for display entry mode
|
|||
#define LCD_ENTRYRIGHT 0x00 |
|||
#define LCD_ENTRYLEFT 0x02 |
|||
#define LCD_ENTRYSHIFTINCREMENT 0x01 |
|||
#define LCD_ENTRYSHIFTDECREMENT 0x00 |
|||
|
|||
// flags for display on/off control
|
|||
#define LCD_DISPLAYON 0x04 |
|||
#define LCD_DISPLAYOFF 0x00 |
|||
#define LCD_CURSORON 0x02 |
|||
#define LCD_CURSOROFF 0x00 |
|||
#define LCD_BLINKON 0x01 |
|||
#define LCD_BLINKOFF 0x00 |
|||
|
|||
// flags for display/cursor shift
|
|||
#define LCD_DISPLAYMOVE 0x08 |
|||
#define LCD_CURSORMOVE 0x00 |
|||
#define LCD_MOVERIGHT 0x04 |
|||
#define LCD_MOVELEFT 0x00 |
|||
|
|||
// flags for function set
|
|||
#define LCD_8BITMODE 0x10 |
|||
#define LCD_4BITMODE 0x00 |
|||
#define LCD_2LINE 0x08 |
|||
#define LCD_1LINE 0x00 |
|||
#define LCD_5x10DOTS 0x04 |
|||
#define LCD_5x8DOTS 0x00 |
|||
|
|||
class LiquidCrystal : public Print { |
|||
public: |
|||
LiquidCrystal(uint8_t rs, uint8_t enable, |
|||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, |
|||
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7); |
|||
LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, |
|||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, |
|||
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7); |
|||
LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, |
|||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3); |
|||
LiquidCrystal(uint8_t rs, uint8_t enable, |
|||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3); |
|||
|
|||
void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable, |
|||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, |
|||
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7); |
|||
|
|||
void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); |
|||
|
|||
void clear(); |
|||
void home(); |
|||
|
|||
void noDisplay(); |
|||
void display(); |
|||
void noBlink(); |
|||
void blink(); |
|||
void noCursor(); |
|||
void cursor(); |
|||
void scrollDisplayLeft(); |
|||
void scrollDisplayRight(); |
|||
void leftToRight(); |
|||
void rightToLeft(); |
|||
void autoscroll(); |
|||
void noAutoscroll(); |
|||
|
|||
void setRowOffsets(int row1, int row2, int row3, int row4); |
|||
void createChar(uint8_t, uint8_t[]); |
|||
void setCursor(uint8_t, uint8_t); |
|||
virtual size_t write(uint8_t); |
|||
void command(uint8_t); |
|||
|
|||
using Print::write; |
|||
private: |
|||
void send(uint8_t, uint8_t); |
|||
void write4bits(uint8_t); |
|||
void write8bits(uint8_t); |
|||
void pulseEnable(); |
|||
|
|||
uint8_t _rs_pin; // LOW: command. HIGH: character.
|
|||
uint8_t _rw_pin; // LOW: write to LCD. HIGH: read from LCD.
|
|||
uint8_t _enable_pin; // activated by a HIGH pulse.
|
|||
uint8_t _data_pins[8]; |
|||
|
|||
uint8_t _displayfunction; |
|||
uint8_t _displaycontrol; |
|||
uint8_t _displaymode; |
|||
|
|||
uint8_t _initialized; |
|||
|
|||
uint8_t _numlines; |
|||
uint8_t _row_offsets[4]; |
|||
}; |
|||
|
|||
#endif |
@ -0,0 +1,356 @@ |
|||
/*
|
|||
Print.cpp - Base class that provides print() and println() |
|||
Copyright (c) 2008 David A. Mellis. All right reserved. |
|||
|
|||
This library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Lesser General Public |
|||
License as published by the Free Software Foundation; either |
|||
version 2.1 of the License, or (at your option) any later version. |
|||
|
|||
This library 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 |
|||
Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public |
|||
License along with this library; if not, write to the Free Software |
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|||
|
|||
Modified 23 November 2006 by David A. Mellis |
|||
Modified 03 August 2015 by Chuck Todd |
|||
*/ |
|||
|
|||
#include <stdlib.h> |
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
#include <math.h> |
|||
#include <inttypes.h> |
|||
#include "Print.h" |
|||
#include <stdarg.h> |
|||
|
|||
#define PrintfEnable 0 |
|||
// Public Methods //////////////////////////////////////////////////////////////
|
|||
|
|||
/* default implementation: may be overridden */ |
|||
size_t Print::write(const uint8_t *buffer, size_t size) |
|||
{ |
|||
|
|||
size_t n = 0; |
|||
while (size--) { |
|||
if (write(*buffer++)) n++; |
|||
else break; |
|||
} |
|||
return n; |
|||
} |
|||
|
|||
|
|||
size_t Print::print(const char str[]) |
|||
{ |
|||
|
|||
//while(1);
|
|||
return write(str); |
|||
} |
|||
|
|||
size_t Print::print(char c) |
|||
{ |
|||
return write(c); |
|||
} |
|||
|
|||
size_t Print::print(unsigned char b, int base) |
|||
{ |
|||
return print((unsigned long) b, base); |
|||
} |
|||
|
|||
size_t Print::print(int n, int base) |
|||
{ |
|||
return print((long) n, base); |
|||
} |
|||
|
|||
size_t Print::print(unsigned int n, int base) |
|||
{ |
|||
return print((unsigned long) n, base); |
|||
} |
|||
|
|||
size_t Print::print(long n, int base) |
|||
{ |
|||
if (base == 0) { |
|||
return write(n); |
|||
} else if (base == 10) { |
|||
if (n < 0) { |
|||
int t = print('-'); |
|||
n = -n; |
|||
return printNumber(n, 10) + t; |
|||
} |
|||
return printNumber(n, 10); |
|||
} else { |
|||
return printNumber(n, base); |
|||
} |
|||
} |
|||
|
|||
size_t Print::print(unsigned long n, int base) |
|||
{ |
|||
if (base == 0) return write(n); |
|||
else return printNumber(n, base); |
|||
} |
|||
|
|||
size_t Print::print(double n, int digits) |
|||
{ |
|||
return printFloat(n, digits); |
|||
} |
|||
|
|||
size_t Print::print(const Printable& x) |
|||
{ |
|||
return x.printTo(*this); |
|||
} |
|||
|
|||
size_t Print::println(void) |
|||
{ |
|||
return write("\r\n"); |
|||
} |
|||
|
|||
size_t Print::println(const char c[]) |
|||
{ |
|||
size_t n = print(c); |
|||
n += println(); |
|||
return n; |
|||
} |
|||
|
|||
size_t Print::println(char c) |
|||
{ |
|||
size_t n = print(c); |
|||
n += println(); |
|||
return n; |
|||
} |
|||
|
|||
size_t Print::println(unsigned char b, int base) |
|||
{ |
|||
size_t n = print(b, base); |
|||
n += println(); |
|||
return n; |
|||
} |
|||
|
|||
size_t Print::println(int num, int base) |
|||
{ |
|||
size_t n = print(num, base); |
|||
n += println(); |
|||
return n; |
|||
} |
|||
|
|||
size_t Print::println(unsigned int num, int base) |
|||
{ |
|||
size_t n = print(num, base); |
|||
n += println(); |
|||
return n; |
|||
} |
|||
|
|||
size_t Print::println(long num, int base) |
|||
{ |
|||
size_t n = print(num, base); |
|||
n += println(); |
|||
return n; |
|||
} |
|||
|
|||
size_t Print::println(unsigned long num, int base) |
|||
{ |
|||
size_t n = print(num, base); |
|||
n += println(); |
|||
return n; |
|||
} |
|||
|
|||
size_t Print::println(double num, int digits) |
|||
{ |
|||
size_t n = print(num, digits); |
|||
n += println(); |
|||
return n; |
|||
} |
|||
|
|||
size_t Print::println(const Printable& x) |
|||
{ |
|||
size_t n = print(x); |
|||
n += println(); |
|||
return n; |
|||
} |
|||
|
|||
// Private Methods /////////////////////////////////////////////////////////////
|
|||
|
|||
size_t Print::printNumber(unsigned long n, uint8_t base) { |
|||
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
|
|||
char *str = &buf[sizeof(buf) - 1]; |
|||
|
|||
*str = '\0'; |
|||
|
|||
// prevent crash if called with base == 1
|
|||
if (base < 2) base = 10; |
|||
|
|||
do { |
|||
unsigned long m = n; |
|||
n /= base; |
|||
char c = m - base * n; |
|||
*--str = c < 10 ? c + '0' : c + 'A' - 10; |
|||
} while(n); |
|||
|
|||
return write(str); |
|||
} |
|||
|
|||
size_t Print::printFloat(double number, uint8_t digits) |
|||
{ |
|||
size_t n = 0; |
|||
|
|||
if (isnan(number)) return print("nan"); |
|||
if (isinf(number)) return print("inf"); |
|||
if (number > 4294967040.0) return print ("ovf"); // constant determined empirically
|
|||
if (number <-4294967040.0) return print ("ovf"); // constant determined empirically
|
|||
|
|||
// Handle negative numbers
|
|||
if (number < 0.0) |
|||
{ |
|||
n += print('-'); |
|||
number = -number; |
|||
} |
|||
|
|||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
|||
double rounding = 0.5; |
|||
for (uint8_t i=0; i<digits; ++i) |
|||
rounding /= 10.0; |
|||
|
|||
number += rounding; |
|||
|
|||
// Extract the integer part of the number and print it
|
|||
unsigned long int_part = (unsigned long)number; |
|||
double remainder = number - (double)int_part; |
|||
n += print(int_part); |
|||
|
|||
// Print the decimal point, but only if there are digits beyond
|
|||
if (digits > 0) { |
|||
n += print("."); |
|||
} |
|||
|
|||
// Extract digits from the remainder one at a time
|
|||
while (digits-- > 0) |
|||
{ |
|||
remainder *= 10.0; |
|||
int toPrint = int(remainder); |
|||
n += print(toPrint); |
|||
remainder -= toPrint; |
|||
} |
|||
|
|||
return n; |
|||
} |
|||
|
|||
|
|||
#if (PrintfEnable == 1) |
|||
size_t Print::printf(const char *argList, ...) |
|||
{ |
|||
const char *ptr; |
|||
double floatNum_f32; |
|||
va_list argp; |
|||
sint16_t num_s16; |
|||
sint32_t num_s32; |
|||
uint16_t num_u16; |
|||
uint32_t num_u32; |
|||
char *str; |
|||
char ch; |
|||
uint8_t numOfDigits; |
|||
|
|||
va_start(argp, argList); |
|||
|
|||
/* Loop through the list to extract all the input arguments */ |
|||
for(ptr = argList; *ptr != '\0'; ptr++) |
|||
{ |
|||
|
|||
ch= *ptr; |
|||
if(ch == '%') /*Check for '%' as there will be format specifier after it */ |
|||
{ |
|||
ptr++; |
|||
ch = *ptr; |
|||
if((ch>=0x30) && (ch<=0x39)) |
|||
{ |
|||
numOfDigits = 0; |
|||
while((ch>=0x30) && (ch<=0x39)) |
|||
{ |
|||
numOfDigits = (numOfDigits * 10) + (ch-0x30); |
|||
ptr++; |
|||
ch = *ptr; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
numOfDigits = 0xff; |
|||
} |
|||
|
|||
|
|||
switch(ch) /* Decode the type of the argument */ |
|||
{ |
|||
|
|||
case 'C': |
|||
case 'c': /* Argument type is of char, hence read char data from the argp */ |
|||
ch = va_arg(argp, int); |
|||
print(ch); |
|||
break; |
|||
|
|||
|
|||
|
|||
case 'd': /* Argument type is of signed integer, hence read 16bit data from the argp */ |
|||
case 'D': |
|||
num_s32 = va_arg(argp, int); |
|||
print(num_s32, 10); |
|||
break; |
|||
|
|||
|
|||
case 'u': |
|||
case 'U': /* Argument type is of integer, hence read 32bit unsigend data */ |
|||
num_u32 = va_arg(argp, uint32_t); |
|||
print(num_u32, 10); |
|||
break; |
|||
|
|||
|
|||
|
|||
|
|||
case 'x': |
|||
case 'X': /* Argument type is of hex, hence hexadecimal data from the argp */ |
|||
num_u32 = va_arg(argp, uint32_t); |
|||
print(num_u32, 16); |
|||
break; |
|||
|
|||
|
|||
case 'b': |
|||
case 'B': /* Argument type is of binary,Read int and convert to binary */ |
|||
num_u32 = va_arg(argp, uint32_t); |
|||
print(num_u32, 2); |
|||
break; |
|||
|
|||
|
|||
|
|||
case 'F': |
|||
case 'f': /* Argument type is of float, hence read double data from the argp */ |
|||
floatNum_f32 = va_arg(argp, double); |
|||
printFloat(floatNum_f32,10); |
|||
break; |
|||
|
|||
|
|||
|
|||
case 'S': |
|||
case 's': /* Argument type is of string, hence get the pointer to sting passed */ |
|||
str = va_arg(argp, char *); |
|||
print(str); |
|||
break; |
|||
|
|||
|
|||
|
|||
case '%': |
|||
print('%'); |
|||
break; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
/* As '%' is not detected transmit the char passed */ |
|||
print(ch); |
|||
} |
|||
} |
|||
|
|||
va_end(argp); |
|||
} |
|||
|
|||
|
|||
#endif |
@ -0,0 +1,85 @@ |
|||
/*
|
|||
Print.h - Base class that provides print() and println() |
|||
Copyright (c) 2008 David A. Mellis. All right reserved. |
|||
|
|||
This library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Lesser General Public |
|||
License as published by the Free Software Foundation; either |
|||
version 2.1 of the License, or (at your option) any later version. |
|||
|
|||
This library 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 |
|||
Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public |
|||
License along with this library; if not, write to the Free Software |
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|||
*/ |
|||
|
|||
#ifndef Print_h |
|||
#define Print_h |
|||
|
|||
|
|||
#include <inttypes.h> |
|||
#include <stdio.h> // for size_t |
|||
#include <string.h> |
|||
|
|||
|
|||
#include "Printable.h" |
|||
|
|||
|
|||
#define DEC 10 |
|||
#define HEX 16 |
|||
#define OCT 8 |
|||
#define BIN 2 |
|||
|
|||
class Print |
|||
{ |
|||
private: |
|||
int write_error; |
|||
size_t printNumber(unsigned long, uint8_t); |
|||
size_t printFloat(double, uint8_t); |
|||
protected: |
|||
void setWriteError(int err = 1) { write_error = err; } |
|||
public: |
|||
Print() : write_error(0) {} |
|||
|
|||
int getWriteError() { return write_error; } |
|||
void clearWriteError() { setWriteError(0); } |
|||
|
|||
virtual size_t write(uint8_t) = 0; |
|||
size_t write(const char *str) { |
|||
|
|||
if (str == NULL) return 0; |
|||
return write((const uint8_t *)str, strlen(str)); |
|||
} |
|||
virtual size_t write(const uint8_t *buffer, size_t size); |
|||
size_t write(const char *buffer, size_t size) { |
|||
return write((const uint8_t *)buffer, size); |
|||
} |
|||
|
|||
size_t print(const char[]); |
|||
size_t print(char); |
|||
size_t print(unsigned char, int = DEC); |
|||
size_t print(int, int = DEC); |
|||
size_t print(unsigned int, int = DEC); |
|||
size_t print(long, int = DEC); |
|||
size_t print(unsigned long, int = DEC); |
|||
size_t print(double, int = 2); |
|||
size_t print(const Printable&); |
|||
|
|||
size_t println(const char[]); |
|||
size_t println(char); |
|||
size_t println(unsigned char, int = DEC); |
|||
size_t println(int, int = DEC); |
|||
size_t println(unsigned int, int = DEC); |
|||
size_t println(long, int = DEC); |
|||
size_t println(unsigned long, int = DEC); |
|||
size_t println(double, int = 2); |
|||
size_t println(const Printable&); |
|||
size_t println(void); |
|||
size_t printf(const char *argList, ...); |
|||
}; |
|||
|
|||
#endif |
@ -0,0 +1,41 @@ |
|||
/*
|
|||
Printable.h - Interface class that allows printing of complex types |
|||
Copyright (c) 2011 Adrian McEwen. All right reserved. |
|||
|
|||
This library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Lesser General Public |
|||
License as published by the Free Software Foundation; either |
|||
version 2.1 of the License, or (at your option) any later version. |
|||
|
|||
This library 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 |
|||
Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public |
|||
License along with this library; if not, write to the Free Software |
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|||
*/ |
|||
|
|||
#ifndef Printable_h |
|||
#define Printable_h |
|||
|
|||
#include <stdlib.h> |
|||
#include <inttypes.h> |
|||
|
|||
class Print; |
|||
|
|||
/** The Printable class provides a way for new classes to allow themselves to be printed.
|
|||
By deriving from Printable and implementing the printTo method, it will then be possible |
|||
for users to print out instances of this class by passing them into the usual |
|||
Print::print and Print::println methods. |
|||
*/ |
|||
|
|||
class Printable |
|||
{ |
|||
public: |
|||
virtual size_t printTo(Print& p) const = 0; |
|||
}; |
|||
|
|||
#endif |
|||
|
@ -0,0 +1,534 @@ |
|||
/*
|
|||
binary.h - Definitions for binary constants |
|||
Copyright (c) 2006 David A. Mellis. All right reserved. |
|||
|
|||
This library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Lesser General Public |
|||
License as published by the Free Software Foundation; either |
|||
version 2.1 of the License, or (at your option) any later version. |
|||
|
|||
This library 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 |
|||
Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public |
|||
License along with this library; if not, write to the Free Software |
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|||
*/ |
|||
|
|||
#ifndef Binary_h |
|||
#define Binary_h |
|||
|
|||
#define B0 0 |
|||
#define B00 0 |
|||
#define B000 0 |
|||
#define B0000 0 |
|||
#define B00000 0 |
|||
#define B000000 0 |
|||
#define B0000000 0 |
|||
#define B00000000 0 |
|||
#define B1 1 |
|||
#define B01 1 |
|||
#define B001 1 |
|||
#define B0001 1 |
|||
#define B00001 1 |
|||
#define B000001 1 |
|||
#define B0000001 1 |
|||
#define B00000001 1 |
|||
#define B10 2 |
|||
#define B010 2 |
|||
#define B0010 2 |
|||
#define B00010 2 |
|||
#define B000010 2 |
|||
#define B0000010 2 |
|||
#define B00000010 2 |
|||
#define B11 3 |
|||
#define B011 3 |
|||
#define B0011 3 |
|||
#define B00011 3 |
|||
#define B000011 3 |
|||
#define B0000011 3 |
|||
#define B00000011 3 |
|||
#define B100 4 |
|||
#define B0100 4 |
|||
#define B00100 4 |
|||
#define B000100 4 |
|||
#define B0000100 4 |
|||
#define B00000100 4 |
|||
#define B101 5 |
|||
#define B0101 5 |
|||
#define B00101 5 |
|||
#define B000101 5 |
|||
#define B0000101 5 |
|||
#define B00000101 5 |
|||
#define B110 6 |
|||
#define B0110 6 |
|||
#define B00110 6 |
|||
#define B000110 6 |
|||
#define B0000110 6 |
|||
#define B00000110 6 |
|||
#define B111 7 |
|||
#define B0111 7 |
|||
#define B00111 7 |
|||
#define B000111 7 |
|||
#define B0000111 7 |
|||
#define B00000111 7 |
|||
#define B1000 8 |
|||
#define B01000 8 |
|||
#define B001000 8 |
|||
#define B0001000 8 |
|||
#define B00001000 8 |
|||
#define B1001 9 |
|||
#define B01001 9 |
|||
#define B001001 9 |
|||
#define B0001001 9 |
|||
#define B00001001 9 |
|||
#define B1010 10 |
|||
#define B01010 10 |
|||
#define B001010 10 |
|||
#define B0001010 10 |
|||
#define B00001010 10 |
|||
#define B1011 11 |
|||
#define B01011 11 |
|||
#define B001011 11 |
|||
#define B0001011 11 |
|||
#define B00001011 11 |
|||
#define B1100 12 |
|||
#define B01100 12 |
|||
#define B001100 12 |
|||
#define B0001100 12 |
|||
#define B00001100 12 |
|||
#define B1101 13 |
|||
#define B01101 13 |
|||
#define B001101 13 |
|||
#define B0001101 13 |
|||
#define B00001101 13 |
|||
#define B1110 14 |
|||
#define B01110 14 |
|||
#define B001110 14 |
|||
#define B0001110 14 |
|||
#define B00001110 14 |
|||
#define B1111 15 |
|||
#define B01111 15 |
|||
#define B001111 15 |
|||
#define B0001111 15 |
|||
#define B00001111 15 |
|||
#define B10000 16 |
|||
#define B010000 16 |
|||
#define B0010000 16 |
|||
#define B00010000 16 |
|||
#define B10001 17 |
|||
#define B010001 17 |
|||
#define B0010001 17 |
|||
#define B00010001 17 |
|||
#define B10010 18 |
|||
#define B010010 18 |
|||
#define B0010010 18 |
|||
#define B00010010 18 |
|||
#define B10011 19 |
|||
#define B010011 19 |
|||
#define B0010011 19 |
|||
#define B00010011 19 |
|||
#define B10100 20 |
|||
#define B010100 20 |
|||
#define B0010100 20 |
|||
#define B00010100 20 |
|||
#define B10101 21 |
|||
#define B010101 21 |
|||
#define B0010101 21 |
|||
#define B00010101 21 |
|||
#define B10110 22 |
|||
#define B010110 22 |
|||
#define B0010110 22 |
|||
#define B00010110 22 |
|||
#define B10111 23 |
|||
#define B010111 23 |
|||
#define B0010111 23 |
|||
#define B00010111 23 |
|||
#define B11000 24 |
|||
#define B011000 24 |
|||
#define B0011000 24 |
|||
#define B00011000 24 |
|||
#define B11001 25 |
|||
#define B011001 25 |
|||
#define B0011001 25 |
|||
#define B00011001 25 |
|||
#define B11010 26 |
|||
#define B011010 26 |
|||
#define B0011010 26 |
|||
#define B00011010 26 |
|||
#define B11011 27 |
|||
#define B011011 27 |
|||
#define B0011011 27 |
|||
#define B00011011 27 |
|||
#define B11100 28 |
|||
#define B011100 28 |
|||
#define B0011100 28 |
|||
#define B00011100 28 |
|||
#define B11101 29 |
|||
#define B011101 29 |
|||
#define B0011101 29 |
|||
#define B00011101 29 |
|||
#define B11110 30 |
|||
#define B011110 30 |
|||
#define B0011110 30 |
|||
#define B00011110 30 |
|||
#define B11111 31 |
|||
#define B011111 31 |
|||
#define B0011111 31 |
|||
#define B00011111 31 |
|||
#define B100000 32 |
|||
#define B0100000 32 |
|||
#define B00100000 32 |
|||
#define B100001 33 |
|||
#define B0100001 33 |
|||
#define B00100001 33 |
|||
#define B100010 34 |
|||
#define B0100010 34 |
|||
#define B00100010 34 |
|||
#define B100011 35 |
|||
#define B0100011 35 |
|||
#define B00100011 35 |
|||
#define B100100 36 |
|||
#define B0100100 36 |
|||
#define B00100100 36 |
|||
#define B100101 37 |
|||
#define B0100101 37 |
|||
#define B00100101 37 |
|||
#define B100110 38 |
|||
#define B0100110 38 |
|||
#define B00100110 38 |
|||
#define B100111 39 |
|||
#define B0100111 39 |
|||
#define B00100111 39 |
|||
#define B101000 40 |
|||
#define B0101000 40 |
|||
#define B00101000 40 |
|||
#define B101001 41 |
|||
#define B0101001 41 |
|||
#define B00101001 41 |
|||
#define B101010 42 |
|||
#define B0101010 42 |
|||
#define B00101010 42 |
|||
#define B101011 43 |
|||
#define B0101011 43 |
|||
#define B00101011 43 |
|||
#define B101100 44 |
|||
#define B0101100 44 |
|||
#define B00101100 44 |
|||
#define B101101 45 |
|||
#define B0101101 45 |
|||
#define B00101101 45 |
|||
#define B101110 46 |
|||
#define B0101110 46 |
|||
#define B00101110 46 |
|||
#define B101111 47 |
|||
#define B0101111 47 |
|||
#define B00101111 47 |
|||
#define B110000 48 |
|||
#define B0110000 48 |
|||
#define B00110000 48 |
|||
#define B110001 49 |
|||
#define B0110001 49 |
|||
#define B00110001 49 |
|||
#define B110010 50 |
|||
#define B0110010 50 |
|||
#define B00110010 50 |
|||
#define B110011 51 |
|||
#define B0110011 51 |
|||
#define B00110011 51 |
|||
#define B110100 52 |
|||
#define B0110100 52 |
|||
#define B00110100 52 |
|||
#define B110101 53 |
|||
#define B0110101 53 |
|||
#define B00110101 53 |
|||
#define B110110 54 |
|||
#define B0110110 54 |
|||
#define B00110110 54 |
|||
#define B110111 55 |
|||
#define B0110111 55 |
|||
#define B00110111 55 |
|||
#define B111000 56 |
|||
#define B0111000 56 |
|||
#define B00111000 56 |
|||
#define B111001 57 |
|||
#define B0111001 57 |
|||
#define B00111001 57 |
|||
#define B111010 58 |
|||
#define B0111010 58 |
|||
#define B00111010 58 |
|||
#define B111011 59 |
|||
#define B0111011 59 |
|||
#define B00111011 59 |
|||
#define B111100 60 |
|||
#define B0111100 60 |
|||
#define B00111100 60 |
|||
#define B111101 61 |
|||
#define B0111101 61 |
|||
#define B00111101 61 |
|||
#define B111110 62 |
|||
#define B0111110 62 |
|||
#define B00111110 62 |
|||
#define B111111 63 |
|||
#define B0111111 63 |
|||
#define B00111111 63 |
|||
#define B1000000 64 |
|||
#define B01000000 64 |
|||
#define B1000001 65 |
|||
#define B01000001 65 |
|||
#define B1000010 66 |
|||
#define B01000010 66 |
|||
#define B1000011 67 |
|||
#define B01000011 67 |
|||
#define B1000100 68 |
|||
#define B01000100 68 |
|||
#define B1000101 69 |
|||
#define B01000101 69 |
|||
#define B1000110 70 |
|||
#define B01000110 70 |
|||
#define B1000111 71 |
|||
#define B01000111 71 |
|||
#define B1001000 72 |
|||
#define B01001000 72 |
|||
#define B1001001 73 |
|||
#define B01001001 73 |
|||
#define B1001010 74 |
|||
#define B01001010 74 |
|||
#define B1001011 75 |
|||
#define B01001011 75 |
|||
#define B1001100 76 |
|||
#define B01001100 76 |
|||
#define B1001101 77 |
|||
#define B01001101 77 |
|||
#define B1001110 78 |
|||
#define B01001110 78 |
|||
#define B1001111 79 |
|||
#define B01001111 79 |
|||
#define B1010000 80 |
|||
#define B01010000 80 |
|||
#define B1010001 81 |
|||
#define B01010001 81 |
|||
#define B1010010 82 |
|||
#define B01010010 82 |
|||
#define B1010011 83 |
|||
#define B01010011 83 |
|||
#define B1010100 84 |
|||
#define B01010100 84 |
|||
#define B1010101 85 |
|||
#define B01010101 85 |
|||
#define B1010110 86 |
|||
#define B01010110 86 |
|||
#define B1010111 87 |
|||
#define B01010111 87 |
|||
#define B1011000 88 |
|||
#define B01011000 88 |
|||
#define B1011001 89 |
|||
#define B01011001 89 |
|||
#define B1011010 90 |
|||
#define B01011010 90 |
|||
#define B1011011 91 |
|||
#define B01011011 91 |
|||
#define B1011100 92 |
|||
#define B01011100 92 |
|||
#define B1011101 93 |
|||
#define B01011101 93 |
|||
#define B1011110 94 |
|||
#define B01011110 94 |
|||
#define B1011111 95 |
|||
#define B01011111 95 |
|||
#define B1100000 96 |
|||
#define B01100000 96 |
|||
#define B1100001 97 |
|||
#define B01100001 97 |
|||
#define B1100010 98 |
|||
#define B01100010 98 |
|||
#define B1100011 99 |
|||
#define B01100011 99 |
|||
#define B1100100 100 |
|||
#define B01100100 100 |
|||
#define B1100101 101 |
|||
#define B01100101 101 |
|||
#define B1100110 102 |
|||
#define B01100110 102 |
|||
#define B1100111 103 |
|||
#define B01100111 103 |
|||
#define B1101000 104 |
|||
#define B01101000 104 |
|||
#define B1101001 105 |
|||
#define B01101001 105 |
|||
#define B1101010 106 |
|||
#define B01101010 106 |
|||
#define B1101011 107 |
|||
#define B01101011 107 |
|||
#define B1101100 108 |
|||
#define B01101100 108 |
|||
#define B1101101 109 |
|||
#define B01101101 109 |
|||
#define B1101110 110 |
|||
#define B01101110 110 |
|||
#define B1101111 111 |
|||
#define B01101111 111 |
|||
#define B1110000 112 |
|||
#define B01110000 112 |
|||
#define B1110001 113 |
|||
#define B01110001 113 |
|||
#define B1110010 114 |
|||
#define B01110010 114 |
|||
#define B1110011 115 |
|||
#define B01110011 115 |
|||
#define B1110100 116 |
|||
#define B01110100 116 |
|||
#define B1110101 117 |
|||
#define B01110101 117 |
|||
#define B1110110 118 |
|||
#define B01110110 118 |
|||
#define B1110111 119 |
|||
#define B01110111 119 |
|||
#define B1111000 120 |
|||
#define B01111000 120 |
|||
#define B1111001 121 |
|||
#define B01111001 121 |
|||
#define B1111010 122 |
|||
#define B01111010 122 |
|||
#define B1111011 123 |
|||
#define B01111011 123 |
|||
#define B1111100 124 |
|||
#define B01111100 124 |
|||
#define B1111101 125 |
|||
#define B01111101 125 |
|||
#define B1111110 126 |
|||
#define B01111110 126 |
|||
#define B1111111 127 |
|||
#define B01111111 127 |
|||
#define B10000000 128 |
|||
#define B10000001 129 |
|||
#define B10000010 130 |
|||
#define B10000011 131 |
|||
#define B10000100 132 |
|||
#define B10000101 133 |
|||
#define B10000110 134 |
|||
#define B10000111 135 |
|||
#define B10001000 136 |
|||
#define B10001001 137 |
|||
#define B10001010 138 |
|||
#define B10001011 139 |
|||
#define B10001100 140 |
|||
#define B10001101 141 |
|||
#define B10001110 142 |
|||
#define B10001111 143 |
|||
#define B10010000 144 |
|||
#define B10010001 145 |
|||
#define B10010010 146 |
|||
#define B10010011 147 |
|||
#define B10010100 148 |
|||
#define B10010101 149 |
|||
#define B10010110 150 |
|||
#define B10010111 151 |
|||
#define B10011000 152 |
|||
#define B10011001 153 |
|||
#define B10011010 154 |
|||
#define B10011011 155 |
|||
#define B10011100 156 |
|||
#define B10011101 157 |
|||
#define B10011110 158 |
|||
#define B10011111 159 |
|||
#define B10100000 160 |
|||
#define B10100001 161 |
|||
#define B10100010 162 |
|||
#define B10100011 163 |
|||
#define B10100100 164 |
|||
#define B10100101 165 |
|||
#define B10100110 166 |
|||
#define B10100111 167 |
|||
#define B10101000 168 |
|||
#define B10101001 169 |
|||
#define B10101010 170 |
|||
#define B10101011 171 |
|||
#define B10101100 172 |
|||
#define B10101101 173 |
|||
#define B10101110 174 |
|||
#define B10101111 175 |
|||
#define B10110000 176 |
|||
#define B10110001 177 |
|||
#define B10110010 178 |
|||
#define B10110011 179 |
|||
#define B10110100 180 |
|||
#define B10110101 181 |
|||
#define B10110110 182 |
|||
#define B10110111 183 |
|||
#define B10111000 184 |
|||
#define B10111001 185 |
|||
#define B10111010 186 |
|||
#define B10111011 187 |
|||
#define B10111100 188 |
|||
#define B10111101 189 |
|||
#define B10111110 190 |
|||
#define B10111111 191 |
|||
#define B11000000 192 |
|||
#define B11000001 193 |
|||
#define B11000010 194 |
|||
#define B11000011 195 |
|||
#define B11000100 196 |
|||
#define B11000101 197 |
|||
#define B11000110 198 |
|||
#define B11000111 199 |
|||
#define B11001000 200 |
|||
#define B11001001 201 |
|||
#define B11001010 202 |
|||
#define B11001011 203 |
|||
#define B11001100 204 |
|||
#define B11001101 205 |
|||
#define B11001110 206 |
|||
#define B11001111 207 |
|||
#define B11010000 208 |
|||
#define B11010001 209 |
|||
#define B11010010 210 |
|||
#define B11010011 211 |
|||
#define B11010100 212 |
|||
#define B11010101 213 |
|||
#define B11010110 214 |
|||
#define B11010111 215 |
|||
#define B11011000 216 |
|||
#define B11011001 217 |
|||
#define B11011010 218 |
|||
#define B11011011 219 |
|||
#define B11011100 220 |
|||
#define B11011101 221 |
|||
#define B11011110 222 |
|||
#define B11011111 223 |
|||
#define B11100000 224 |
|||
#define B11100001 225 |
|||
#define B11100010 226 |
|||
#define B11100011 227 |
|||
#define B11100100 228 |
|||
#define B11100101 229 |
|||
#define B11100110 230 |
|||
#define B11100111 231 |
|||
#define B11101000 232 |
|||
#define B11101001 233 |
|||
#define B11101010 234 |
|||
#define B11101011 235 |
|||
#define B11101100 236 |
|||
#define B11101101 237 |
|||
#define B11101110 238 |
|||
#define B11101111 239 |
|||
#define B11110000 240 |
|||
#define B11110001 241 |
|||
#define B11110010 242 |
|||
#define B11110011 243 |
|||
#define B11110100 244 |
|||
#define B11110101 245 |
|||
#define B11110110 246 |
|||
#define B11110111 247 |
|||
#define B11111000 248 |
|||
#define B11111001 249 |
|||
#define B11111010 250 |
|||
#define B11111011 251 |
|||
#define B11111100 252 |
|||
#define B11111101 253 |
|||
#define B11111110 254 |
|||
#define B11111111 255 |
|||
|
|||
#endif |
File diff suppressed because it is too large
@ -0,0 +1,109 @@ |
|||
/*-----------------------------------------------------------------------
|
|||
/ Low level disk interface modlue include file (C)ChaN, 2015 |
|||
/-----------------------------------------------------------------------*/ |
|||
|
|||
#ifndef _DISKIO_DEFINED |
|||
#define _DISKIO_DEFINED |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
#define _DISKIO_WRITE 1 /* 1: Enable disk_write function */ |
|||
#define _DISKIO_IOCTL 1 /* 1: Enable disk_ioctl fucntion */ |
|||
#define _DISKIO_ISDIO 0 /* 1: Enable iSDIO control fucntion */ |
|||
|
|||
#include "integer.h" |
|||
|
|||
|
|||
/* Status of Disk Functions */ |
|||
typedef BYTE DSTATUS; |
|||
|
|||
/* Results of Disk Functions */ |
|||
typedef enum { |
|||
RES_OK = 0, /* 0: Successful */ |
|||
RES_ERROR, /* 1: R/W Error */ |
|||
RES_WRPRT, /* 2: Write Protected */ |
|||
RES_NOTRDY, /* 3: Not Ready */ |
|||
RES_PARERR /* 4: Invalid Parameter */ |
|||
} DRESULT; |
|||
|
|||
|
|||
#if _DISKIO_ISDIO |
|||
/* Command structure for iSDIO ioctl command */ |
|||
typedef struct { |
|||
BYTE func; /* Function number: 0..7 */ |
|||
WORD ndata; /* Number of bytes to transfer: 1..512, or mask + data */ |
|||
DWORD addr; /* Register address: 0..0x1FFFF */ |
|||
void* data; /* Pointer to the data (to be written | read buffer) */ |
|||
} SDIO_CMD; |
|||
#endif |
|||
|
|||
|
|||
/*---------------------------------------*/ |
|||
/* Prototypes for disk control functions */ |
|||
|
|||
|
|||
DSTATUS disk_initialize (BYTE pdrv); |
|||
DSTATUS disk_status (BYTE pdrv); |
|||
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); |
|||
#if _DISKIO_WRITE |
|||
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); |
|||
#endif |
|||
#if _DISKIO_IOCTL |
|||
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); |
|||
#endif |
|||
|
|||
|
|||
/* Disk Status Bits (DSTATUS) */ |
|||
#define STA_NOINIT 0x01 /* Drive not initialized */ |
|||
#define STA_NODISK 0x02 /* No medium in the drive */ |
|||
#define STA_PROTECT 0x04 /* Write protected */ |
|||
|
|||
|
|||
/* Command code for disk_ioctrl fucntion */ |
|||
|
|||
/* Generic command (Used by FatFs) */ |
|||
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */ |
|||
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */ |
|||
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */ |
|||
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */ |
|||
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ |
|||
|
|||
/* Generic command (Not used by FatFs) */ |
|||
#define CTRL_FORMAT 5 /* Create physical format on the media */ |
|||
#define CTRL_POWER_IDLE 6 /* Put the device idle state */ |
|||
#define CTRL_POWER_OFF 7 /* Put the device off state */ |
|||
#define CTRL_LOCK 8 /* Lock media removal */ |
|||
#define CTRL_UNLOCK 9 /* Unlock media removal */ |
|||
#define CTRL_EJECT 10 /* Eject media */ |
|||
|
|||
/* MMC/SDC specific ioctl command (Not used by FatFs) */ |
|||
#define MMC_GET_TYPE 50 /* Get card type */ |
|||
#define MMC_GET_CSD 51 /* Get CSD */ |
|||
#define MMC_GET_CID 52 /* Get CID */ |
|||
#define MMC_GET_OCR 53 /* Get OCR */ |
|||
#define MMC_GET_SDSTAT 54 /* Get SD status */ |
|||
#define ISDIO_READ 55 /* Read data form SD iSDIO register */ |
|||
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ |
|||
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ |
|||
|
|||
/* ATA/CF specific ioctl command (Not used by FatFs) */ |
|||
#define ATA_GET_REV 60 /* Get F/W revision */ |
|||
#define ATA_GET_MODEL 61 /* Get model name */ |
|||
#define ATA_GET_SN 62 /* Get serial number */ |
|||
|
|||
|
|||
/* MMC card type flags (MMC_GET_TYPE) */ |
|||
#define CT_MMC 0x01 /* MMC ver 3 */ |
|||
#define CT_SD1 0x02 /* SD ver 1 */ |
|||
#define CT_SD2 0x04 /* SD ver 2 */ |
|||
#define CT_SDC (CT_SD1|CT_SD2) /* SD */ |
|||
#define CT_BLOCK 0x08 /* Block addressing */ |
|||
|
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif |
File diff suppressed because it is too large
@ -0,0 +1,364 @@ |
|||
/*----------------------------------------------------------------------------/
|
|||
/ FatFs - Generic FAT Filesystem module R0.13 / |
|||
/-----------------------------------------------------------------------------/ |
|||
/ |
|||
/ Copyright (C) 2017, ChaN, all right reserved. |
|||
/ |
|||
/ FatFs module is an open source software. Redistribution and use of FatFs in |
|||
/ source and binary forms, with or without modification, are permitted provided |
|||
/ that the following condition is met: |
|||
|
|||
/ 1. Redistributions of source code must retain the above copyright notice, |
|||
/ this condition and the following disclaimer. |
|||
/ |
|||
/ This software is provided by the copyright holder and contributors "AS IS" |
|||
/ and any warranties related to this software are DISCLAIMED. |
|||
/ The copyright owner or contributors be NOT LIABLE for any damages caused |
|||
/ by use of this software. |
|||
/ |
|||
/----------------------------------------------------------------------------*/ |
|||
|
|||
|
|||
#ifndef FF_DEFINED |
|||
#define FF_DEFINED 87030 /* Revision ID */ |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
#include "integer.h" /* Basic integer types */ |
|||
#include "ffconf.h" /* FatFs configuration options */ |
|||
|
|||
#if FF_DEFINED != FFCONF_DEF |
|||
#error Wrong configuration file (ffconf.h). |
|||
#endif |
|||
|
|||
|
|||
|
|||
/* Definitions of volume management */ |
|||
|
|||
#if FF_MULTI_PARTITION /* Multiple partition configuration */ |
|||
typedef struct { |
|||
BYTE pd; /* Physical drive number */ |
|||
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ |
|||
} PARTITION; |
|||
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ |
|||
#endif |
|||
|
|||
|
|||
|
|||
/* Type of path name strings on FatFs API */ |
|||
|
|||
#if FF_LFN_UNICODE && FF_USE_LFN /* Unicode (UTF-16) string */ |
|||
#ifndef _INC_TCHAR |
|||
typedef WCHAR TCHAR; |
|||
#define _T(x) L ## x |
|||
#define _TEXT(x) L ## x |
|||
#define _INC_TCHAR |
|||
#endif |
|||
#else /* ANSI/OEM string */ |
|||
#ifndef _INC_TCHAR |
|||
typedef char TCHAR; |
|||
#define _T(x) x |
|||
#define _TEXT(x) x |
|||
#define _INC_TCHAR |
|||
#endif |
|||
#endif |
|||
|
|||
|
|||
|
|||
/* Type of file size variables */ |
|||
|
|||
#if FF_FS_EXFAT |
|||
#if !FF_USE_LFN |
|||
#error LFN must be enabled when enable exFAT |
|||
#endif |
|||
typedef QWORD FSIZE_t; |
|||
#else |
|||
typedef DWORD FSIZE_t; |
|||
#endif |
|||
|
|||
|
|||
|
|||
/* Filesystem object structure (FATFS) */ |
|||
|
|||
typedef struct { |
|||
BYTE fs_type; /* Filesystem type (0:N/A) */ |
|||
BYTE pdrv; /* Physical drive number */ |
|||
BYTE n_fats; /* Number of FATs (1 or 2) */ |
|||
BYTE wflag; /* win[] flag (b0:dirty) */ |
|||
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ |
|||
WORD id; /* Volume mount ID */ |
|||
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ |
|||
WORD csize; /* Cluster size [sectors] */ |
|||
#if FF_MAX_SS != FF_MIN_SS |
|||
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ |
|||
#endif |
|||
#if FF_USE_LFN |
|||
WCHAR* lfnbuf; /* LFN working buffer */ |
|||
#endif |
|||
#if FF_FS_EXFAT |
|||
BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */ |
|||
#endif |
|||
#if FF_FS_REENTRANT |
|||
FF_SYNC_t sobj; /* Identifier of sync object */ |
|||
#endif |
|||
#if !FF_FS_READONLY |
|||
DWORD last_clst; /* Last allocated cluster */ |
|||
DWORD free_clst; /* Number of free clusters */ |
|||
#endif |
|||
#if FF_FS_RPATH |
|||
DWORD cdir; /* Current directory start cluster (0:root) */ |
|||
#if FF_FS_EXFAT |
|||
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ |
|||
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ |
|||
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ |
|||
#endif |
|||
#endif |
|||
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ |
|||
DWORD fsize; /* Size of an FAT [sectors] */ |
|||
DWORD volbase; /* Volume base sector */ |
|||
DWORD fatbase; /* FAT base sector */ |
|||
DWORD dirbase; /* Root directory base sector/cluster */ |
|||
DWORD database; /* Data base sector */ |
|||
DWORD winsect; /* Current sector appearing in the win[] */ |
|||
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ |
|||
} FATFS; |
|||
|
|||
|
|||
|
|||
/* Object ID and allocation information (FFOBJID) */ |
|||
|
|||
typedef struct { |
|||
FATFS* fs; /* Pointer to the hosting volume of this object */ |
|||
WORD id; /* Hosting volume mount ID */ |
|||
BYTE attr; /* Object attribute */ |
|||
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:flagmented in this session, b2:sub-directory stretched) */ |
|||
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */ |
|||
FSIZE_t objsize; /* Object size (valid when sclust != 0) */ |
|||
#if FF_FS_EXFAT |
|||
DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */ |
|||
DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */ |
|||
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ |
|||
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ |
|||
DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */ |
|||
#endif |
|||
#if FF_FS_LOCK |
|||
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ |
|||
#endif |
|||
} FFOBJID; |
|||
|
|||
|
|||
|
|||
/* File object structure (FIL) */ |
|||
|
|||
typedef struct { |
|||
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ |
|||
BYTE flag; /* File status flags */ |
|||
BYTE err; /* Abort flag (error code) */ |
|||
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ |
|||
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */ |
|||
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */ |
|||
#if !FF_FS_READONLY |
|||
DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */ |
|||
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */ |
|||
#endif |
|||
#if FF_USE_FASTSEEK |
|||
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ |
|||
#endif |
|||
#if !FF_FS_TINY |
|||
BYTE buf[FF_MAX_SS]; /* File private data read/write window */ |
|||
#endif |
|||
} FIL; |
|||
|
|||
|
|||
|
|||
/* Directory object structure (DIR) */ |
|||
|
|||
typedef struct { |
|||
FFOBJID obj; /* Object identifier */ |
|||
DWORD dptr; /* Current read/write offset */ |
|||
DWORD clust; /* Current cluster */ |
|||
DWORD sect; /* Current sector (0:Read operation has terminated) */ |
|||
BYTE* dir; /* Pointer to the directory item in the win[] */ |
|||
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */ |
|||
#if FF_USE_LFN |
|||
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */ |
|||
#endif |
|||
#if FF_USE_FIND |
|||
const TCHAR* pat; /* Pointer to the name matching pattern */ |
|||
#endif |
|||
} DIR; |
|||
|
|||
|
|||
|
|||
/* File information structure (FILINFO) */ |
|||
|
|||
typedef struct { |
|||
FSIZE_t fsize; /* File size */ |
|||
WORD fdate; /* Modified date */ |
|||
WORD ftime; /* Modified time */ |
|||
BYTE fattrib; /* File attribute */ |
|||
#if FF_USE_LFN |
|||
TCHAR altname[13]; /* Altenative file name */ |
|||
TCHAR fname[FF_MAX_LFN + 1]; /* Primary file name */ |
|||
#else |
|||
TCHAR fname[13]; /* File name */ |
|||
#endif |
|||
} FILINFO; |
|||
|
|||
|
|||
|
|||
/* File function return code (FRESULT) */ |
|||
|
|||
typedef enum { |
|||
FR_OK = 0, /* (0) Succeeded */ |
|||
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ |
|||
FR_INT_ERR, /* (2) Assertion failed */ |
|||
FR_NOT_READY, /* (3) The physical drive cannot work */ |
|||
FR_NO_FILE, /* (4) Could not find the file */ |
|||
FR_NO_PATH, /* (5) Could not find the path */ |
|||
FR_INVALID_NAME, /* (6) The path name format is invalid */ |
|||
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ |
|||
FR_EXIST, /* (8) Access denied due to prohibited access */ |
|||
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ |
|||
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ |
|||
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ |
|||
FR_NOT_ENABLED, /* (12) The volume has no work area */ |
|||
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ |
|||
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ |
|||
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ |
|||
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ |
|||
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ |
|||
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ |
|||
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ |
|||
} FRESULT; |
|||
|
|||
|
|||
|
|||
/*--------------------------------------------------------------*/ |
|||
/* FatFs module application interface */ |
|||
|
|||
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ |
|||
FRESULT f_close (FIL* fp); /* Close an open file object */ |
|||
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ |
|||
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ |
|||
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ |
|||
FRESULT f_truncate (FIL* fp); /* Truncate the file */ |
|||
FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ |
|||
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ |
|||
FRESULT f_closedir (DIR* dp); /* Close an open directory */ |
|||
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ |
|||
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ |
|||
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */ |
|||
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ |
|||
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ |
|||
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ |
|||
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ |
|||
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */ |
|||
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */ |
|||
FRESULT f_chdir (const TCHAR* path); /* Change current directory */ |
|||
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ |
|||
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ |
|||
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ |
|||
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ |
|||
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ |
|||
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ |
|||
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */ |
|||
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ |
|||
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ |
|||
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */ |
|||
FRESULT f_setcp (WORD cp); /* Set current code page */ |
|||
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ |
|||
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ |
|||
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ |
|||
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ |
|||
|
|||
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) |
|||
#define f_error(fp) ((fp)->err) |
|||
#define f_tell(fp) ((fp)->fptr) |
|||
#define f_size(fp) ((fp)->obj.objsize) |
|||
#define f_rewind(fp) f_lseek((fp), 0) |
|||
#define f_rewinddir(dp) f_readdir((dp), 0) |
|||
#define f_rmdir(path) f_unlink(path) |
|||
#define f_unmount(path) f_mount(0, path, 0) |
|||
|
|||
#ifndef EOF |
|||
#define EOF (-1) |
|||
#endif |
|||
|
|||
|
|||
|
|||
|
|||
/*--------------------------------------------------------------*/ |
|||
/* Additional user defined functions */ |
|||
|
|||
/* RTC function */ |
|||
#if !FF_FS_READONLY && !FF_FS_NORTC |
|||
DWORD get_fattime (void); |
|||
#endif |
|||
|
|||
/* LFN support functions */ |
|||
#if FF_USE_LFN /* Code conversion (defined in unicode.c) */ |
|||
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ |
|||
WCHAR ff_uni2oem (WCHAR uni, WORD cp); /* Unicode to OEM code conversion */ |
|||
WCHAR ff_wtoupper (WCHAR uni); /* Unicode upper-case conversion */ |
|||
#endif |
|||
#if FF_USE_LFN == 3 /* Dynamic memory allocation */ |
|||
void* ff_memalloc (UINT msize); /* Allocate memory block */ |
|||
void ff_memfree (void* mblock); /* Free memory block */ |
|||
#endif |
|||
|
|||
/* Sync functions */ |
|||
#if FF_FS_REENTRANT |
|||
int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */ |
|||
int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */ |
|||
void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */ |
|||
int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */ |
|||
#endif |
|||
|
|||
|
|||
|
|||
|
|||
/*--------------------------------------------------------------*/ |
|||
/* Flags and offset address */ |
|||
|
|||
|
|||
/* File access mode and open method flags (3rd argument of f_open) */ |
|||
#define FA_READ 0x01 |
|||
#define FA_WRITE 0x02 |
|||
#define FA_OPEN_EXISTING 0x00 |
|||
#define FA_CREATE_NEW 0x04 |
|||
#define FA_CREATE_ALWAYS 0x08 |
|||
#define FA_OPEN_ALWAYS 0x10 |
|||
#define FA_OPEN_APPEND 0x30 |
|||
|
|||
/* Fast seek controls (2nd argument of f_lseek) */ |
|||
#define CREATE_LINKMAP ((FSIZE_t)0 - 1) |
|||
|
|||
/* Format options (2nd argument of f_mkfs) */ |
|||
#define FM_FAT 0x01 |
|||
#define FM_FAT32 0x02 |
|||
#define FM_EXFAT 0x04 |
|||
#define FM_ANY 0x07 |
|||
#define FM_SFD 0x08 |
|||
|
|||
/* Filesystem type (FATFS.fs_type) */ |
|||
#define FS_FAT12 1 |
|||
#define FS_FAT16 2 |
|||
#define FS_FAT32 3 |
|||
#define FS_EXFAT 4 |
|||
|
|||
/* File attribute bits for directory entry (FILINFO.fattrib) */ |
|||
#define AM_RDO 0x01 /* Read only */ |
|||
#define AM_HID 0x02 /* Hidden */ |
|||
#define AM_SYS 0x04 /* System */ |
|||
#define AM_DIR 0x10 /* Directory */ |
|||
#define AM_ARC 0x20 /* Archive */ |
|||
|
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif /* FF_DEFINED */ |
@ -0,0 +1,269 @@ |
|||
/*---------------------------------------------------------------------------/
|
|||
/ FatFs - Configuration file |
|||
/---------------------------------------------------------------------------*/ |
|||
|
|||
#define FFCONF_DEF 87030 /* Revision ID */ |
|||
|
|||
/*---------------------------------------------------------------------------/
|
|||
/ Function Configurations |
|||
/---------------------------------------------------------------------------*/ |
|||
|
|||
#define FF_FS_READONLY 0 |
|||
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
|
|||
/ Read-only configuration removes writing API functions, f_write(), f_sync(), |
|||
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() |
|||
/ and optional writing functions as well. */ |
|||
|
|||
|
|||
#define FF_FS_MINIMIZE 0 |
|||
/* This option defines minimization level to remove some basic API functions.
|
|||
/ |
|||
/ 0: All basic functions are enabled. |
|||
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() |
|||
/ are removed. |
|||
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. |
|||
/ 3: f_lseek() function is removed in addition to 2. */ |
|||
|
|||
|
|||
#define FF_USE_STRFUNC 0 |
|||
/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
|
|||
/ |
|||
/ 0: Disable string functions. |
|||
/ 1: Enable without LF-CRLF conversion. |
|||
/ 2: Enable with LF-CRLF conversion. */ |
|||
|
|||
|
|||
#define FF_USE_FIND 1 |
|||
/* This option switches filtered directory read functions, f_findfirst() and
|
|||
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ |
|||
|
|||
|
|||
#define FF_USE_MKFS 1 |
|||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ |
|||
|
|||
|
|||
#define FF_USE_FASTSEEK 0 |
|||
/* This option switches fast seek function. (0:Disable or 1:Enable) */ |
|||
|
|||
|
|||
#define FF_USE_EXPAND 0 |
|||
/* This option switches f_expand function. (0:Disable or 1:Enable) */ |
|||
|
|||
|
|||
#define FF_USE_CHMOD 1 |
|||
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
|
|||
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ |
|||
|
|||
|
|||
#define FF_USE_LABEL 1 |
|||
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
|||
/ (0:Disable or 1:Enable) */ |
|||
|
|||
|
|||
#define FF_USE_FORWARD 0 |
|||
/* This option switches f_forward() function. (0:Disable or 1:Enable) */ |
|||
|
|||
|
|||
/*---------------------------------------------------------------------------/
|
|||
/ Locale and Namespace Configurations |
|||
/---------------------------------------------------------------------------*/ |
|||
|
|||
#define FF_CODE_PAGE 932 |
|||
/* This option specifies the OEM code page to be used on the target system.
|
|||
/ Incorrect code page setting can cause a file open failure. |
|||
/ |
|||
/ 437 - U.S. |
|||
/ 720 - Arabic |
|||
/ 737 - Greek |
|||
/ 771 - KBL |
|||
/ 775 - Baltic |
|||
/ 850 - Latin 1 |
|||
/ 852 - Latin 2 |
|||
/ 855 - Cyrillic |
|||
/ 857 - Turkish |
|||
/ 860 - Portuguese |
|||
/ 861 - Icelandic |
|||
/ 862 - Hebrew |
|||
/ 863 - Canadian French |
|||
/ 864 - Arabic |
|||
/ 865 - Nordic |
|||
/ 866 - Russian |
|||
/ 869 - Greek 2 |
|||
/ 932 - Japanese (DBCS) |
|||
/ 936 - Simplified Chinese (DBCS) |
|||
/ 949 - Korean (DBCS) |
|||
/ 950 - Traditional Chinese (DBCS) |
|||
/ 0 - Include all code pages above and configured by f_setcp() |
|||
*/ |
|||
|
|||
|
|||
#define FF_USE_LFN 1 |
|||
#define FF_MAX_LFN 255 |
|||
/* The FF_USE_LFN switches the support for LFN (long file name).
|
|||
/ |
|||
/ 0: Disable LFN. FF_MAX_LFN has no effect. |
|||
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. |
|||
/ 2: Enable LFN with dynamic working buffer on the STACK. |
|||
/ 3: Enable LFN with dynamic working buffer on the HEAP. |
|||
/ |
|||
/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added |
|||
/ to the project. The working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and |
|||
/ additional 608 bytes at exFAT enabled. FF_MAX_LFN can be in range from 12 to 255. |
|||
/ It should be set 255 to support full featured LFN operations. |
|||
/ When use stack for the working buffer, take care on stack overflow. When use heap |
|||
/ memory for the working buffer, memory management functions, ff_memalloc() and |
|||
/ ff_memfree(), must be added to the project. */ |
|||
|
|||
|
|||
#define FF_LFN_UNICODE 0 |
|||
/* This option switches character encoding on the API, 0:ANSI/OEM or 1:UTF-16,
|
|||
/ when LFN is enabled. Also behavior of string I/O functions will be affected by |
|||
/ this option. When LFN is not enabled, this option has no effect. |
|||
*/ |
|||
|
|||
|
|||
#define FF_STRF_ENCODE 3 |
|||
/* When FF_LFN_UNICODE = 1 with LFN enabled, string I/O functions, f_gets(),
|
|||
/ f_putc(), f_puts and f_printf() convert the character encoding in it. |
|||
/ This option selects assumption of character encoding ON THE FILE to be |
|||
/ read/written via those functions. |
|||
/ |
|||
/ 0: ANSI/OEM |
|||
/ 1: UTF-16LE |
|||
/ 2: UTF-16BE |
|||
/ 3: UTF-8 |
|||
*/ |
|||
|
|||
|
|||
#define FF_FS_RPATH 2 |
|||
/* This option configures support for relative path.
|
|||
/ |
|||
/ 0: Disable relative path and remove related functions. |
|||
/ 1: Enable relative path. f_chdir() and f_chdrive() are available. |
|||
/ 2: f_getcwd() function is available in addition to 1. |
|||
*/ |
|||
|
|||
|
|||
/*---------------------------------------------------------------------------/
|
|||
/ Drive/Volume Configurations |
|||
/---------------------------------------------------------------------------*/ |
|||
|
|||
#define FF_VOLUMES 1 |
|||
/* Number of volumes (logical drives) to be used. (1-10) */ |
|||
|
|||
|
|||
#define FF_STR_VOLUME_ID 0 |
|||
#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" |
|||
/* FF_STR_VOLUME_ID switches string support for volume ID.
|
|||
/ When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive |
|||
/ number in the path name. FF_VOLUME_STRS defines the drive ID strings for each |
|||
/ logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for |
|||
/ the drive ID strings are: A-Z and 0-9. */ |
|||
|
|||
|
|||
#define FF_MULTI_PARTITION 0 |
|||
/* This option switches support for multiple volumes on the physical drive.
|
|||
/ By default (0), each logical drive number is bound to the same physical drive |
|||
/ number and only an FAT volume found on the physical drive will be mounted. |
|||
/ When this function is enabled (1), each logical drive number can be bound to |
|||
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() |
|||
/ funciton will be available. */ |
|||
|
|||
|
|||
#define FF_MIN_SS 512 |
|||
#define FF_MAX_SS 512 |
|||
/* This set of options configures the range of sector size to be supported. (512,
|
|||
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and |
|||
/ harddisk. But a larger value may be required for on-board flash memory and some |
|||
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured |
|||
/ for variable sector size mode and disk_ioctl() function needs to implement |
|||
/ GET_SECTOR_SIZE command. */ |
|||
|
|||
|
|||
#define FF_USE_TRIM 0 |
|||
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
|
|||
/ To enable Trim function, also CTRL_TRIM command should be implemented to the |
|||
/ disk_ioctl() function. */ |
|||
|
|||
|
|||
#define FF_FS_NOFSINFO 0 |
|||
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
|
|||
/ option, and f_getfree() function at first time after volume mount will force |
|||
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. |
|||
/ |
|||
/ bit0=0: Use free cluster count in the FSINFO if available. |
|||
/ bit0=1: Do not trust free cluster count in the FSINFO. |
|||
/ bit1=0: Use last allocated cluster number in the FSINFO if available. |
|||
/ bit1=1: Do not trust last allocated cluster number in the FSINFO. |
|||
*/ |
|||
|
|||
|
|||
|
|||
/*---------------------------------------------------------------------------/
|
|||
/ System Configurations |
|||
/---------------------------------------------------------------------------*/ |
|||
|
|||
#define FF_FS_TINY 0 |
|||
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
|
|||
/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. |
|||
/ Instead of private sector buffer eliminated from the file object, common sector |
|||
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ |
|||
|
|||
|
|||
#define FF_FS_EXFAT 0 |
|||
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
|||
/ When enable exFAT, also LFN needs to be enabled. |
|||
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ |
|||
|
|||
|
|||
#define FF_FS_NORTC 0 |
|||
#define FF_NORTC_MON 1 |
|||
#define FF_NORTC_MDAY 1 |
|||
#define FF_NORTC_YEAR 2016 |
|||
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
|
|||
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable |
|||
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp |
|||
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. |
|||
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be |
|||
/ added to the project to read current time form real-time clock. FF_NORTC_MON, |
|||
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. |
|||
/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ |
|||
|
|||
|
|||
#define FF_FS_LOCK 0 |
|||
/* The option FF_FS_LOCK switches file lock function to control duplicated file open
|
|||
/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY |
|||
/ is 1. |
|||
/ |
|||
/ 0: Disable file lock function. To avoid volume corruption, application program |
|||
/ should avoid illegal open, remove and rename to the open objects. |
|||
/ >0: Enable file lock function. The value defines how many files/sub-directories |
|||
/ can be opened simultaneously under file lock control. Note that the file |
|||
/ lock control is independent of re-entrancy. */ |
|||
|
|||
|
|||
#define FF_FS_REENTRANT 0 |
|||
#define FF_FS_TIMEOUT 1000 |
|||
#define FF_SYNC_t HANDLE |
|||
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
|
|||
/ module itself. Note that regardless of this option, file access to different |
|||
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() |
|||
/ and f_fdisk() function, are always not re-entrant. Only file/directory access |
|||
/ to the same volume is under control of this function. |
|||
/ |
|||
/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. |
|||
/ 1: Enable re-entrancy. Also user provided synchronization handlers, |
|||
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() |
|||
/ function, must be added to the project. Samples are available in |
|||
/ option/syscall.c. |
|||
/ |
|||
/ The FF_FS_TIMEOUT defines timeout period in unit of time tick. |
|||
/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, |
|||
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be |
|||
/ included somewhere in the scope of ff.h. */ |
|||
|
|||
/* #include <windows.h> // O/S definitions */ |
|||
|
|||
|
|||
|
|||
/*--- End of configuration options ---*/ |
File diff suppressed because it is too large
@ -0,0 +1,38 @@ |
|||
/*-------------------------------------------*/ |
|||
/* Integer type definitions for FatFs module */ |
|||
/*-------------------------------------------*/ |
|||
|
|||
#ifndef _FF_INTEGER |
|||
#define _FF_INTEGER |
|||
|
|||
#ifdef _WIN32 /* FatFs development platform */ |
|||
|
|||
#include <windows.h> |
|||
#include <tchar.h> |
|||
typedef unsigned __int64 QWORD; |
|||
|
|||
|
|||
#else /* Embedded platform */ |
|||
|
|||
/* These types MUST be 16-bit or 32-bit */ |
|||
typedef int INT; |
|||
typedef unsigned int UINT; |
|||
|
|||
/* This type MUST be 8-bit */ |
|||
typedef unsigned char BYTE; |
|||
|
|||
/* These types MUST be 16-bit */ |
|||
typedef short SHORT; |
|||
typedef unsigned short WORD; |
|||
typedef unsigned short WCHAR; |
|||
|
|||
/* These types MUST be 32-bit */ |
|||
typedef long LONG; |
|||
typedef unsigned long DWORD; |
|||
|
|||
/* This type MUST be 64-bit (Remove this for C89 compatibility) */ |
|||
typedef unsigned long long QWORD; |
|||
|
|||
#endif |
|||
|
|||
#endif |
@ -0,0 +1,745 @@ |
|||
/*------------------------------------------------------------------------*/ |
|||
/* LPCXpresso176x: MMCv3/SDv1/SDv2 (SPI mode) control module */ |
|||
/*------------------------------------------------------------------------*/ |
|||
/*
|
|||
/ Copyright (C) 2015, ChaN, all right reserved. |
|||
/ |
|||
/ * This software is a free software and there is NO WARRANTY. |
|||
/ * No restriction on use. You can use, modify and redistribute it for |
|||
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. |
|||
/ * Redistributions of source code must retain the above copyright notice. |
|||
/ |
|||
/-------------------------------------------------------------------------*/ |
|||
|
|||
#define SSP_CH 1 /* SSP channel to use (0:SSP0, 1:SSP1) */ |
|||
|
|||
#define CCLK 100000000UL /* cclk frequency [Hz] */ |
|||
#define PCLK_SSP 50000000UL /* PCLK frequency to be supplied for SSP [Hz] */ |
|||
#define SCLK_FAST 25000000UL /* SCLK frequency under normal operation [Hz] */ |
|||
#define SCLK_SLOW 400000UL /* SCLK frequency under initialization [Hz] */ |
|||
|
|||
//#define MMC_CD (!(FIO2PIN1 & _BV(1))) /* Card detect (yes:true, no:false, default:true) */
|
|||
#define MMC_WP 0 /* Write protected (yes:true, no:false, default:false) */ |
|||
|
|||
#if SSP_CH == 0 |
|||
#define SSPxDR SSP0DR |
|||
#define SSPxSR SSP0SR |
|||
#define SSPxCR0 SSP0CR0 |
|||
#define SSPxCR1 SSP0CR1 |
|||
#define SSPxCPSR SSP0CPSR |
|||
#define CS_LOW() {FIO0CLR2 = _BV(0);} /* Set P0.16 low */ |
|||
#define CS_HIGH() {FIO0SET2 = _BV(0);} /* Set P0.16 high */ |
|||
#define PCSSPx PCSSP0 |
|||
#define PCLKSSPx PCLK_SSP0 |
|||
#define ATTACH_SSP() {\ |
|||
__set_PINSEL(0, 15, 2); /* SCK0 */\ |
|||
__set_PINSEL(0, 17, 2); /* MISO0 */\ |
|||
__set_PINSEL(0, 18, 2); /* MOSI0 */\ |
|||
FIO0DIR |= _BV(16); /* CS# (P0.16) */\ |
|||
} |
|||
#elif SSP_CH == 1 |
|||
#define SSPxDR SSP1DR |
|||
#define SSPxSR SSP1SR |
|||
#define SSPxCR0 SSP1CR0 |
|||
#define SSPxCR1 SSP1CR1 |
|||
#define SSPxCPSR SSP1CPSR |
|||
#define CS_LOW() {FIO0CLR0 = _BV(6);} /* Set P0.6 low */ |
|||
#define CS_HIGH() {FIO0SET0 = _BV(6);} /* Set P0.6 high */ |
|||
#define PCSSPx PCSSP1 |
|||
#define PCLKSSPx PCLK_SSP1 |
|||
#define ATTACH_SSP() {\ |
|||
__set_PINSEL(0, 7, 2); /* SCK1 */\ |
|||
__set_PINSEL(0, 8, 2); /* MISO1 */\ |
|||
__set_PINSEL(0, 9, 2); /* MOSI1 */\ |
|||
FIO0DIR |= _BV(6); /* CS# (P0.6) */\ |
|||
} |
|||
#endif |
|||
|
|||
#if PCLK_SSP * 1 == CCLK |
|||
#define PCLKDIV_SSP PCLKDIV_1 |
|||
#elif PCLK_SSP * 2 == CCLK |
|||
#define PCLKDIV_SSP PCLKDIV_2 |
|||
#elif PCLK_SSP * 4 == CCLK |
|||
#define PCLKDIV_SSP PCLKDIV_4 |
|||
#elif PCLK_SSP * 8 == CCLK |
|||
#define PCLKDIV_SSP PCLKDIV_8 |
|||
#else |
|||
#error Invalid CCLK:PCLK_SSP combination. |
|||
#endif |
|||
|
|||
|
|||
#define FCLK_FAST() { SSPxCR0 = (SSPxCR0 & 0x00FF) | ((PCLK_SSP / 2 / SCLK_FAST) - 1) << 8; } |
|||
#define FCLK_SLOW() { SSPxCR0 = (SSPxCR0 & 0x00FF) | ((PCLK_SSP / 2 / SCLK_SLOW) - 1) << 8; } |
|||
|
|||
|
|||
|
|||
/*--------------------------------------------------------------------------
|
|||
|
|||
Module Private Functions |
|||
|
|||
---------------------------------------------------------------------------*/ |
|||
|
|||
#include "LPC176x.h" |
|||
#include "diskio.h" |
|||
|
|||
|
|||
/* MMC/SD command */ |
|||
#define CMD0 (0) /* GO_IDLE_STATE */ |
|||
#define CMD1 (1) /* SEND_OP_COND (MMC) */ |
|||
#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */ |
|||
#define CMD8 (8) /* SEND_IF_COND */ |
|||
#define CMD9 (9) /* SEND_CSD */ |
|||
#define CMD10 (10) /* SEND_CID */ |
|||
#define CMD12 (12) /* STOP_TRANSMISSION */ |
|||
#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */ |
|||
#define CMD16 (16) /* SET_BLOCKLEN */ |
|||
#define CMD17 (17) /* READ_SINGLE_BLOCK */ |
|||
#define CMD18 (18) /* READ_MULTIPLE_BLOCK */ |
|||
#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */ |
|||
#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */ |
|||
#define CMD24 (24) /* WRITE_BLOCK */ |
|||
#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */ |
|||
#define CMD32 (32) /* ERASE_ER_BLK_START */ |
|||
#define CMD33 (33) /* ERASE_ER_BLK_END */ |
|||
#define CMD38 (38) /* ERASE */ |
|||
#define CMD48 (48) /* READ_EXTR_SINGLE */ |
|||
#define CMD49 (49) /* WRITE_EXTR_SINGLE */ |
|||
#define CMD55 (55) /* APP_CMD */ |
|||
#define CMD58 (58) /* READ_OCR */ |
|||
|
|||
|
|||
static volatile |
|||
DSTATUS Stat = STA_NOINIT; /* Physical drive status */ |
|||
|
|||
static volatile |
|||
UINT Timer1, Timer2; /* 1kHz decrement timer stopped at zero (disk_timerproc()) */ |
|||
|
|||
static |
|||
BYTE CardType; /* Card type flags */ |
|||
|
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Send/Receive data to the MMC (Platform dependent) */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
|
|||
/* Exchange a byte */ |
|||
static |
|||
BYTE xchg_spi ( |
|||
BYTE dat /* Data to send */ |
|||
) |
|||
{ |
|||
SSPxDR = dat; |
|||
while (SSPxSR & 0x10) ; |
|||
return SSPxDR; |
|||
} |
|||
|
|||
|
|||
/* Receive multiple byte */ |
|||
static |
|||
void rcvr_spi_multi ( |
|||
BYTE *buff, /* Pointer to data buffer */ |
|||
UINT btr /* Number of bytes to receive (16, 64 or 512) */ |
|||
) |
|||
{ |
|||
UINT n; |
|||
WORD d; |
|||
|
|||
|
|||
SSPxCR0 |= 0x000F; /* Select 16-bit mode */ |
|||
|
|||
for (n = 0; n < 8; n++) /* Push 8 frames into pipeline */ |
|||
SSPxDR = 0xFFFF; |
|||
btr -= 16; |
|||
|
|||
while (btr >= 2) { /* Receive the data block into buffer */ |
|||
btr -= 2; |
|||
while (!(SSPxSR & _BV(2))) ; /* Wait for any data in receive FIFO */ |
|||
d = SSPxDR; |
|||
SSPxDR = 0xFFFF; |
|||
*buff++ = d >> 8; |
|||
*buff++ = d; |
|||
} |
|||
|
|||
for (n = 0; n < 8; n++) { /* Pop remaining frames from pipeline */ |
|||
while (!(SSPxSR & _BV(2))) ; |
|||
d = SSPxDR; |
|||
*buff++ = d >> 8; |
|||
*buff++ = d; |
|||
} |
|||
|
|||
SSPxCR0 &= 0xFFF7; /* Select 8-bit mode */ |
|||
} |
|||
|
|||
|
|||
#if _DISKIO_WRITE |
|||
/* Send multiple byte */ |
|||
static |
|||
void xmit_spi_multi ( |
|||
const BYTE *buff, /* Pointer to the data */ |
|||
UINT btx /* Number of bytes to send (multiple of 16) */ |
|||
) |
|||
{ |
|||
UINT n; |
|||
WORD d; |
|||
|
|||
|
|||
SSPxCR0 |= 0x000F; /* Select 16-bit mode */ |
|||
|
|||
for (n = 0; n < 8; n++) { /* Push 8 frames into pipeline */ |
|||
d = *buff++; |
|||
d = d << 8 | *buff++; |
|||
SSPxDR = d; |
|||
} |
|||
btx -= 16; |
|||
|
|||
while (btx >= 2) { /* Transmit data block */ |
|||
btx -= 2; |
|||
d = *buff++; |
|||
d = d << 8 | *buff++; |
|||
while (!(SSPxSR & _BV(2))) ; /* Wait for any data in receive FIFO */ |
|||
SSPxDR; SSPxDR = d; |
|||
} |
|||
|
|||
for (n = 0; n < 8; n++) { /* Flush pipeline */ |
|||
while (!(SSPxSR & _BV(2))) ; |
|||
SSPxDR; |
|||
} |
|||
|
|||
SSPxCR0 &= 0xFFF7; /* Select 8-bit mode */ |
|||
} |
|||
#endif |
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Wait for card ready */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
|
|||
static |
|||
int wait_ready ( /* 1:Ready, 0:Timeout */ |
|||
UINT wt /* Timeout [ms] */ |
|||
) |
|||
{ |
|||
BYTE d; |
|||
|
|||
|
|||
Timer2 = wt; |
|||
do { |
|||
d = xchg_spi(0xFF); |
|||
|
|||
/* This loop takes a time. Insert rot_rdq() here for multitask envilonment. */ |
|||
|
|||
} while (d != 0xFF && Timer2); /* Wait for card goes ready or timeout */ |
|||
|
|||
return (d == 0xFF) ? 1 : 0; |
|||
} |
|||
|
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Deselect card and release SPI */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
|
|||
static |
|||
void deselect (void) |
|||
{ |
|||
CS_HIGH(); /* CS = H */ |
|||
xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */ |
|||
} |
|||
|
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Select card and wait for ready */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
|
|||
static |
|||
int select (void) /* 1:OK, 0:Timeout */ |
|||
{ |
|||
CS_LOW(); /* CS = L */ |
|||
xchg_spi(0xFF); /* Dummy clock (force DO enabled) */ |
|||
|
|||
if (wait_ready(500)) return 1; /* Leading busy check: Wait for card ready */ |
|||
|
|||
deselect(); /* Timeout */ |
|||
return 0; |
|||
} |
|||
|
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Control SPI module (Platform dependent) */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
|
|||
static |
|||
void power_on (void) /* Enable SSP module and attach it to I/O pads */ |
|||
{ |
|||
__set_PCONP(PCSSPx, 1); /* Enable SSP module */ |
|||
__set_PCLKSEL(PCLKSSPx, PCLKDIV_SSP); /* Select PCLK frequency for SSP */ |
|||
SSPxCPSR = 2; /* CPSDVSR=2 */ |
|||
SSPxCR0 = 0x0007; /* Set mode: SPI mode 0, 8-bit */ |
|||
SSPxCR1 = 0x2; /* Enable SSP with Master */ |
|||
ATTACH_SSP(); /* Attach SSP module to I/O pads */ |
|||
CS_HIGH(); /* Set CS# high */ |
|||
|
|||
for (Timer1 = 10; Timer1; ) ; /* 10ms */ |
|||
} |
|||
|
|||
|
|||
static |
|||
void power_off (void) /* Disable SPI function */ |
|||
{ |
|||
select(); /* Wait for card ready */ |
|||
deselect(); |
|||
} |
|||
|
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Receive a data packet from the MMC */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
|
|||
static |
|||
int rcvr_datablock ( /* 1:OK, 0:Error */ |
|||
BYTE *buff, /* Data buffer */ |
|||
UINT btr /* Data block length (byte) */ |
|||
) |
|||
{ |
|||
BYTE token; |
|||
|
|||
|
|||
Timer1 = 200; |
|||
do { /* Wait for DataStart token in timeout of 200ms */ |
|||
token = xchg_spi(0xFF); |
|||
|
|||
/* This loop will take a time. Insert rot_rdq() here for multitask envilonment. */ |
|||
|
|||
} while ((token == 0xFF) && Timer1); |
|||
if(token != 0xFE) return 0; /* Function fails if invalid DataStart token or timeout */ |
|||
|
|||
rcvr_spi_multi(buff, btr); /* Store trailing data to the buffer */ |
|||
xchg_spi(0xFF); xchg_spi(0xFF); /* Discard CRC */ |
|||
|
|||
return 1; /* Function succeeded */ |
|||
} |
|||
|
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Send a data packet to the MMC */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
|
|||
#if _DISKIO_WRITE |
|||
static |
|||
int xmit_datablock ( /* 1:OK, 0:Failed */ |
|||
const BYTE *buff, /* Ponter to 512 byte data to be sent */ |
|||
BYTE token /* Token */ |
|||
) |
|||
{ |
|||
BYTE resp; |
|||
|
|||
|
|||
if (!wait_ready(500)) return 0; /* Leading busy check: Wait for card ready to accept data block */ |
|||
|
|||
xchg_spi(token); /* Send token */ |
|||
if (token == 0xFD) return 1; /* Do not send data if token is StopTran */ |
|||
|
|||
xmit_spi_multi(buff, 512); /* Data */ |
|||
xchg_spi(0xFF); xchg_spi(0xFF); /* Dummy CRC */ |
|||
|
|||
resp = xchg_spi(0xFF); /* Receive data resp */ |
|||
|
|||
return (resp & 0x1F) == 0x05 ? 1 : 0; /* Data was accepted or not */ |
|||
|
|||
/* Busy check is done at next transmission */ |
|||
} |
|||
#endif |
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Send a command packet to the MMC */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
|
|||
static |
|||
BYTE send_cmd ( /* Return value: R1 resp (bit7==1:Failed to send) */ |
|||
BYTE cmd, /* Command index */ |
|||
DWORD arg /* Argument */ |
|||
) |
|||
{ |
|||
BYTE n, res; |
|||
|
|||
|
|||
if (cmd & 0x80) { /* Send a CMD55 prior to ACMD<n> */ |
|||
cmd &= 0x7F; |
|||
res = send_cmd(CMD55, 0); |
|||
if (res > 1) return res; |
|||
} |
|||
|
|||
/* Select the card and wait for ready except to stop multiple block read */ |
|||
if (cmd != CMD12) { |
|||
deselect(); |
|||
if (!select()) return 0xFF; |
|||
} |
|||
|
|||
/* Send command packet */ |
|||
xchg_spi(0x40 | cmd); /* Start + command index */ |
|||
xchg_spi((BYTE)(arg >> 24)); /* Argument[31..24] */ |
|||
xchg_spi((BYTE)(arg >> 16)); /* Argument[23..16] */ |
|||
xchg_spi((BYTE)(arg >> 8)); /* Argument[15..8] */ |
|||
xchg_spi((BYTE)arg); /* Argument[7..0] */ |
|||
n = 0x01; /* Dummy CRC + Stop */ |
|||
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */ |
|||
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */ |
|||
xchg_spi(n); |
|||
|
|||
/* Receive command resp */ |
|||
if (cmd == CMD12) xchg_spi(0xFF); /* Diacard following one byte when CMD12 */ |
|||
n = 10; /* Wait for response (10 bytes max) */ |
|||
do |
|||
res = xchg_spi(0xFF); |
|||
while ((res & 0x80) && --n); |
|||
|
|||
return res; /* Return received response */ |
|||
} |
|||
|
|||
|
|||
|
|||
/*--------------------------------------------------------------------------
|
|||
|
|||
Public Functions |
|||
|
|||
---------------------------------------------------------------------------*/ |
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Initialize disk drive */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
|
|||
DSTATUS disk_initialize ( |
|||
BYTE drv /* Physical drive number (0) */ |
|||
) |
|||
{ |
|||
BYTE n, cmd, ty, ocr[4]; |
|||
|
|||
|
|||
if (drv) return STA_NOINIT; /* Supports only drive 0 */ |
|||
power_on(); /* Initialize SPI */ |
|||
|
|||
if (Stat & STA_NODISK) return Stat; /* Is a card existing in the soket? */ |
|||
|
|||
FCLK_SLOW(); |
|||
for (n = 10; n; n--) xchg_spi(0xFF); /* Send 80 dummy clocks */ |
|||
|
|||
ty = 0; |
|||
if (send_cmd(CMD0, 0) == 1) { /* Put the card SPI state */ |
|||
Timer1 = 1000; /* Initialization timeout = 1 sec */ |
|||
if (send_cmd(CMD8, 0x1AA) == 1) { /* Is the catd SDv2? */ |
|||
for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); /* Get 32 bit return value of R7 resp */ |
|||
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* Does the card support 2.7-3.6V? */ |
|||
while (Timer1 && send_cmd(ACMD41, 1UL << 30)) ; /* Wait for end of initialization with ACMD41(HCS) */ |
|||
if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ |
|||
for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); |
|||
ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* Check if the card is SDv2 */ |
|||
} |
|||
} |
|||
} else { /* Not an SDv2 card */ |
|||
if (send_cmd(ACMD41, 0) <= 1) { /* SDv1 or MMCv3? */ |
|||
ty = CT_SD1; cmd = ACMD41; /* SDv1 (ACMD41(0)) */ |
|||
} else { |
|||
ty = CT_MMC; cmd = CMD1; /* MMCv3 (CMD1(0)) */ |
|||
} |
|||
while (Timer1 && send_cmd(cmd, 0)) ; /* Wait for the card leaves idle state */ |
|||
if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Set block length: 512 */ |
|||
ty = 0; |
|||
} |
|||
} |
|||
CardType = ty; /* Card type */ |
|||
deselect(); |
|||
|
|||
if (ty) { /* OK */ |
|||
FCLK_FAST(); /* Set fast clock */ |
|||
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT flag */ |
|||
} else { /* Failed */ |
|||
power_off(); |
|||
Stat = STA_NOINIT; |
|||
} |
|||
|
|||
return Stat; |
|||
} |
|||
|
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Get disk status */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
|
|||
DSTATUS disk_status ( |
|||
BYTE drv /* Physical drive number (0) */ |
|||
) |
|||
{ |
|||
if (drv) return STA_NOINIT; /* Supports only drive 0 */ |
|||
|
|||
return Stat; /* Return disk status */ |
|||
} |
|||
|
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Read sector(s) */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
|
|||
DRESULT disk_read ( |
|||
BYTE drv, /* Physical drive number (0) */ |
|||
BYTE *buff, /* Pointer to the data buffer to store read data */ |
|||
DWORD sector, /* Start sector number (LBA) */ |
|||
UINT count /* Number of sectors to read (1..128) */ |
|||
) |
|||
{ |
|||
BYTE cmd; |
|||
|
|||
|
|||
if (drv || !count) return RES_PARERR; /* Check parameter */ |
|||
if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */ |
|||
if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ot BA conversion (byte addressing cards) */ |
|||
|
|||
cmd = count > 1 ? CMD18 : CMD17; /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */ |
|||
if (send_cmd(cmd, sector) == 0) { |
|||
do { |
|||
if (!rcvr_datablock(buff, 512)) break; |
|||
buff += 512; |
|||
} while (--count); |
|||
if (cmd == CMD18) send_cmd(CMD12, 0); /* STOP_TRANSMISSION */ |
|||
} |
|||
deselect(); |
|||
|
|||
return count ? RES_ERROR : RES_OK; /* Return result */ |
|||
} |
|||
|
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Write sector(s) */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
|
|||
#if _DISKIO_WRITE |
|||
DRESULT disk_write ( |
|||
BYTE drv, /* Physical drive number (0) */ |
|||
const BYTE *buff, /* Ponter to the data to write */ |
|||
DWORD sector, /* Start sector number (LBA) */ |
|||
UINT count /* Number of sectors to write (1..128) */ |
|||
) |
|||
{ |
|||
if (drv || !count) return RES_PARERR; /* Check parameter */ |
|||
if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check drive status */ |
|||
if (Stat & STA_PROTECT) return RES_WRPRT; /* Check write protect */ |
|||
|
|||
if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ==> BA conversion (byte addressing cards) */ |
|||
|
|||
if (count == 1) { /* Single sector write */ |
|||
if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */ |
|||
&& xmit_datablock(buff, 0xFE)) { |
|||
count = 0; |
|||
} |
|||
} |
|||
else { /* Multiple sector write */ |
|||
if (CardType & CT_SDC) send_cmd(ACMD23, count); /* Predefine number of sectors */ |
|||
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */ |
|||
do { |
|||
if (!xmit_datablock(buff, 0xFC)) break; |
|||
buff += 512; |
|||
} while (--count); |
|||
if (!xmit_datablock(0, 0xFD)) count = 1; /* STOP_TRAN token */ |
|||
} |
|||
} |
|||
deselect(); |
|||
|
|||
return count ? RES_ERROR : RES_OK; /* Return result */ |
|||
} |
|||
#endif |
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Miscellaneous drive controls other than data read/write */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
|
|||
#if _DISKIO_IOCTL |
|||
|
|||
DRESULT disk_ioctl ( |
|||
BYTE drv, /* Physical drive number (0) */ |
|||
BYTE cmd, /* Control command code */ |
|||
void *buff /* Pointer to the conrtol data */ |
|||
) |
|||
{ |
|||
DRESULT res; |
|||
BYTE n, csd[16], *ptr = buff; |
|||
DWORD *dp, st, ed, csize; |
|||
#if _DISKIO_ISDIO |
|||
SDIO_CMD *sdio = buff; |
|||
BYTE rc, *buf; |
|||
UINT dc; |
|||
#endif |
|||
|
|||
if (drv) return RES_PARERR; /* Check parameter */ |
|||
if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */ |
|||
|
|||
res = RES_ERROR; |
|||
|
|||
switch (cmd) { |
|||
case CTRL_SYNC: /* Wait for end of internal write process of the drive */ |
|||
if (select()) res = RES_OK; |
|||
break; |
|||
|
|||
case GET_SECTOR_COUNT: /* Get drive capacity in unit of sector (DWORD) */ |
|||
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { |
|||
if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */ |
|||
csize = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1; |
|||
*(DWORD*)buff = csize << 10; |
|||
} else { /* SDC ver 1.XX or MMC ver 3 */ |
|||
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2; |
|||
csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1; |
|||
*(DWORD*)buff = csize << (n - 9); |
|||
} |
|||
res = RES_OK; |
|||
} |
|||
break; |
|||
|
|||
case GET_BLOCK_SIZE: /* Get erase block size in unit of sector (DWORD) */ |
|||
if (CardType & CT_SD2) { /* SDC ver 2.00 */ |
|||
if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */ |
|||
xchg_spi(0xFF); |
|||
if (rcvr_datablock(csd, 16)) { /* Read partial block */ |
|||
for (n = 64 - 16; n; n--) xchg_spi(0xFF); /* Purge trailing data */ |
|||
*(DWORD*)buff = 16UL << (csd[10] >> 4); |
|||
res = RES_OK; |
|||
} |
|||
} |
|||
} else { /* SDC ver 1.XX or MMC */ |
|||
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */ |
|||
if (CardType & CT_SD1) { /* SDC ver 1.XX */ |
|||
*(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1); |
|||
} else { /* MMC */ |
|||
*(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1); |
|||
} |
|||
res = RES_OK; |
|||
} |
|||
} |
|||
break; |
|||
|
|||
case CTRL_TRIM: /* Erase a block of sectors (used when _USE_TRIM in ffconf.h is 1) */ |
|||
if (!(CardType & CT_SDC)) break; /* Check if the card is SDC */ |
|||
if (disk_ioctl(drv, MMC_GET_CSD, csd)) break; /* Get CSD */ |
|||
if (!(csd[0] >> 6) && !(csd[10] & 0x40)) break; /* Check if sector erase can be applied to the card */ |
|||
dp = buff; st = dp[0]; ed = dp[1]; /* Load sector block */ |
|||
if (!(CardType & CT_BLOCK)) { |
|||
st *= 512; ed *= 512; |
|||
} |
|||
if (send_cmd(CMD32, st) == 0 && send_cmd(CMD33, ed) == 0 && send_cmd(CMD38, 0) == 0 && wait_ready(30000)) { /* Erase sector block */ |
|||
res = RES_OK; /* FatFs does not check result of this command */ |
|||
} |
|||
break; |
|||
|
|||
/* Following commands are never used by FatFs module */ |
|||
|
|||
case MMC_GET_TYPE: /* Get MMC/SDC type (BYTE) */ |
|||
*ptr = CardType; |
|||
res = RES_OK; |
|||
break; |
|||
|
|||
case MMC_GET_CSD: /* Read CSD (16 bytes) */ |
|||
if (send_cmd(CMD9, 0) == 0 && rcvr_datablock(ptr, 16)) { /* READ_CSD */ |
|||
res = RES_OK; |
|||
} |
|||
break; |
|||
|
|||
case MMC_GET_CID: /* Read CID (16 bytes) */ |
|||
if (send_cmd(CMD10, 0) == 0 && rcvr_datablock(ptr, 16)) { /* READ_CID */ |
|||
res = RES_OK; |
|||
} |
|||
break; |
|||
|
|||
case MMC_GET_OCR: /* Read OCR (4 bytes) */ |
|||
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */ |
|||
for (n = 4; n; n--) *ptr++ = xchg_spi(0xFF); |
|||
res = RES_OK; |
|||
} |
|||
break; |
|||
|
|||
case MMC_GET_SDSTAT: /* Read SD status (64 bytes) */ |
|||
if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */ |
|||
xchg_spi(0xFF); |
|||
if (rcvr_datablock(ptr, 64)) res = RES_OK; |
|||
} |
|||
break; |
|||
#if _DISKIO_ISDIO |
|||
case ISDIO_READ: |
|||
sdio = buff; |
|||
if (send_cmd(CMD48, 0x80000000 | sdio->func << 28 | sdio->addr << 9 | ((sdio->ndata - 1) & 0x1FF)) == 0) { |
|||
for (Timer1 = 1000; (rc = xchg_spi(0xFF)) == 0xFF && Timer1; ) ; |
|||
if (rc == 0xFE) { |
|||
for (buf = sdio->data, dc = sdio->ndata; dc; dc--) *buf++ = xchg_spi(0xFF); |
|||
for (dc = 514 - sdio->ndata; dc; dc--) xchg_spi(0xFF); |
|||
res = RES_OK; |
|||
} |
|||
} |
|||
break; |
|||
case ISDIO_WRITE: |
|||
sdio = buff; |
|||
if (send_cmd(CMD49, 0x80000000 | sdio->func << 28 | sdio->addr << 9 | ((sdio->ndata - 1) & 0x1FF)) == 0) { |
|||
xchg_spi(0xFF); xchg_spi(0xFE); |
|||
for (buf = sdio->data, dc = sdio->ndata; dc; dc--) xchg_spi(*buf++); |
|||
for (dc = 514 - sdio->ndata; dc; dc--) xchg_spi(0xFF); |
|||
if ((xchg_spi(0xFF) & 0x1F) == 0x05) res = RES_OK; |
|||
} |
|||
break; |
|||
case ISDIO_MRITE: |
|||
sdio = buff; |
|||
if (send_cmd(CMD49, 0x84000000 | sdio->func << 28 | sdio->addr << 9 | sdio->ndata >> 8) == 0) { |
|||
xchg_spi(0xFF); xchg_spi(0xFE); |
|||
xchg_spi(sdio->ndata); |
|||
for (dc = 513; dc; dc--) xchg_spi(0xFF); |
|||
if ((xchg_spi(0xFF) & 0x1F) == 0x05) res = RES_OK; |
|||
} |
|||
break; |
|||
#endif |
|||
default: |
|||
res = RES_PARERR; |
|||
} |
|||
|
|||
deselect(); |
|||
return res; |
|||
} |
|||
#endif |
|||
|
|||
|
|||
/*-----------------------------------------------------------------------*/ |
|||
/* Device timer function */ |
|||
/*-----------------------------------------------------------------------*/ |
|||
/* This function must be called from timer interrupt routine in period
|
|||
/ of 1 ms to generate card control timing. |
|||
*/ |
|||
|
|||
void disk_timerproc (void) |
|||
{ |
|||
WORD n; |
|||
BYTE s; |
|||
|
|||
|
|||
n = Timer1; /* 1kHz decrement timer stopped at 0 */ |
|||
if (n) Timer1 = --n; |
|||
n = Timer2; |
|||
if (n) Timer2 = --n; |
|||
|
|||
s = Stat; |
|||
if (MMC_WP) { /* Write protected */ |
|||
s |= STA_PROTECT; |
|||
} else { /* Write enabled */ |
|||
s &= ~STA_PROTECT; |
|||
} |
|||
//if (MMC_CD) { /* Card is in socket */
|
|||
s &= ~STA_NODISK; |
|||
//} else { /* Socket empty */
|
|||
// s |= (STA_NODISK | STA_NOINIT);
|
|||
//}
|
|||
Stat = s; |
|||
} |
|||
|
@ -0,0 +1,91 @@ |
|||
/*------------------------------------------------------------------------/
|
|||
/ LPC176x RTC control module |
|||
/-------------------------------------------------------------------------/ |
|||
/ |
|||
/ Copyright (C) 2011, ChaN, all right reserved. |
|||
/ |
|||
/ * This software is a free software and there is NO WARRANTY. |
|||
/ * No restriction on use. You can use, modify and redistribute it for |
|||
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. |
|||
/ * Redistributions of source code must retain the above copyright notice. |
|||
/ |
|||
/-------------------------------------------------------------------------*/ |
|||
|
|||
#include "rtc176x.h" |
|||
|
|||
|
|||
int rtc_initialize (void) |
|||
{ |
|||
/* Enable PCLK to the RTC */ |
|||
__set_PCONP(PCRTC, 1); |
|||
|
|||
/* Start RTC with external XTAL */ |
|||
RTC_CCR = 0x11; |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
|
|||
|
|||
int rtc_gettime (RTC *rtc) /* 1:RTC valid, 0:RTC volatiled */ |
|||
{ |
|||
DWORD d, t; |
|||
|
|||
|
|||
do { |
|||
t = RTC_CTIME0; |
|||
d = RTC_CTIME1; |
|||
} while (t != RTC_CTIME0 || d != RTC_CTIME1); |
|||
|
|||
if (RTC_AUX & _BV(4)) { /* If power fail has been detected, return default time. */ |
|||
rtc->sec = 0; rtc->min = 0; rtc->hour = 0; |
|||
rtc->wday = 0; rtc->mday = 1; rtc->month = 1; rtc->year = 2014; |
|||
return 0; |
|||
} |
|||
|
|||
rtc->sec = t & 63; |
|||
rtc->min = (t >> 8) & 63; |
|||
rtc->hour = (t >> 16) & 31; |
|||
rtc->wday = (t >> 24) & 7; |
|||
rtc->mday = d & 31; |
|||
rtc->month = (d >> 8) & 15; |
|||
rtc->year = (d >> 16) & 4095; |
|||
return 1; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
int rtc_settime (const RTC *rtc) |
|||
{ |
|||
RTC_CCR = 0x12; /* Stop RTC */ |
|||
|
|||
/* Update RTC registers */ |
|||
RTC_SEC = rtc->sec; |
|||
RTC_MIN = rtc->min; |
|||
RTC_HOUR = rtc->hour; |
|||
RTC_DOW = rtc->wday; |
|||
RTC_DOM = rtc->mday; |
|||
RTC_MONTH = rtc->month; |
|||
RTC_YEAR = rtc->year; |
|||
|
|||
RTC_AUX = _BV(4); /* Clear power fail flag */ |
|||
RTC_CCR = 0x11; /* Restart RTC, Disable calibration feature */ |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
DWORD get_fattime (void) { |
|||
RTC rtc; |
|||
|
|||
/* Get local time */ |
|||
rtc_gettime(&rtc); |
|||
|
|||
/* Pack date and time into a DWORD variable */ |
|||
return ((DWORD)(rtc.year - 1980) << 25) |
|||
| ((DWORD)rtc.month << 21) |
|||
| ((DWORD)rtc.mday << 16) |
|||
| ((DWORD)rtc.hour << 11) |
|||
| ((DWORD)rtc.min << 5) |
|||
| ((DWORD)rtc.sec >> 1); |
|||
} |
@ -0,0 +1,22 @@ |
|||
#ifndef _RTC_DEFINED |
|||
#define _RTC_DEFINE |
|||
|
|||
#include "integer.h" |
|||
#include "LPC176x.h" |
|||
|
|||
typedef struct { |
|||
WORD year; /* 1..4095 */ |
|||
BYTE month; /* 1..12 */ |
|||
BYTE mday; /* 1.. 31 */ |
|||
BYTE wday; /* 1..7 */ |
|||
BYTE hour; /* 0..23 */ |
|||
BYTE min; /* 0..59 */ |
|||
BYTE sec; /* 0..59 */ |
|||
} RTC; |
|||
|
|||
int rtc_initialize (void); /* Initialize RTC */ |
|||
int rtc_gettime (RTC*); /* Get time */ |
|||
int rtc_settime (const RTC*); /* Set time */ |
|||
DWORD get_fattime (void); |
|||
|
|||
#endif |
@ -0,0 +1,36 @@ |
|||
[Version] |
|||
Signature="$Windows NT$" |
|||
Class=Ports |
|||
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} |
|||
Provider=%PROVIDER% |
|||
DriverVer =04/14/2008, 5.1.2600.5512 |
|||
|
|||
[Manufacturer] |
|||
%PROVIDER%=DeviceList,ntamd64 |
|||
|
|||
|
|||
[DeviceList] |
|||
%DESCRIPTION%=LPC1768USB, USB\VID_1D50&PID_6029&MI_00 |
|||
|
|||
[DeviceList.ntamd64] |
|||
%DESCRIPTION%=LPC1768USB, USB\VID_1D50&PID_6029&MI_00 |
|||
|
|||
|
|||
[LPC1768USB] |
|||
include=mdmcpq.inf |
|||
CopyFiles=FakeModemCopyFileSection |
|||
AddReg=LowerFilterAddReg,SerialPropPageAddReg |
|||
|
|||
[LPC1768USB.Services] |
|||
include=mdmcpq.inf |
|||
AddService=usbser, 0x00000002, LowerFilter_Service_Inst |
|||
|
|||
[SerialPropPageAddReg] |
|||
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" |
|||
|
|||
|
|||
[Strings] |
|||
PROVIDER = "marlinfw.org" |
|||
DRIVER.SVC = "Marlin USB Driver" |
|||
DESCRIPTION= "Marlin USB Serial" |
|||
COMPOSITE = "Marlin USB VCOM" |
@ -0,0 +1,254 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: CDC.h |
|||
* Purpose: USB Communication Device Class Definitions |
|||
* Version: V1.20 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC family microcontroller devices only. Nothing |
|||
* else gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
#ifndef __CDC_H |
|||
#define __CDC_H |
|||
|
|||
extern "C" { |
|||
#include <lpc_types.h> |
|||
} |
|||
|
|||
#if defined ( __GNUC__ ) |
|||
#define __packed __attribute__((__packed__)) |
|||
#endif |
|||
/*----------------------------------------------------------------------------
|
|||
* Definitions based on usbcdc11.pdf (www.usb.org) |
|||
*---------------------------------------------------------------------------*/ |
|||
// Communication device class specification version 1.10
|
|||
#define CDC_V1_10 0x0110 |
|||
|
|||
// Communication interface class code
|
|||
// (usbcdc11.pdf, 4.2, Table 15)
|
|||
#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02 |
|||
|
|||
// Communication interface class subclass codes
|
|||
// (usbcdc11.pdf, 4.3, Table 16)
|
|||
#define CDC_DIRECT_LINE_CONTROL_MODEL 0x01 |
|||
#define CDC_ABSTRACT_CONTROL_MODEL 0x02 |
|||
#define CDC_TELEPHONE_CONTROL_MODEL 0x03 |
|||
#define CDC_MULTI_CHANNEL_CONTROL_MODEL 0x04 |
|||
#define CDC_CAPI_CONTROL_MODEL 0x05 |
|||
#define CDC_ETHERNET_NETWORKING_CONTROL_MODEL 0x06 |
|||
#define CDC_ATM_NETWORKING_CONTROL_MODEL 0x07 |
|||
|
|||
// Communication interface class control protocol codes
|
|||
// (usbcdc11.pdf, 4.4, Table 17)
|
|||
#define CDC_PROTOCOL_COMMON_AT_COMMANDS 0x01 |
|||
|
|||
// Data interface class code
|
|||
// (usbcdc11.pdf, 4.5, Table 18)
|
|||
#define CDC_DATA_INTERFACE_CLASS 0x0A |
|||
|
|||
// Data interface class protocol codes
|
|||
// (usbcdc11.pdf, 4.7, Table 19)
|
|||
#define CDC_PROTOCOL_ISDN_BRI 0x30 |
|||
#define CDC_PROTOCOL_HDLC 0x31 |
|||
#define CDC_PROTOCOL_TRANSPARENT 0x32 |
|||
#define CDC_PROTOCOL_Q921_MANAGEMENT 0x50 |
|||
#define CDC_PROTOCOL_Q921_DATA_LINK 0x51 |
|||
#define CDC_PROTOCOL_Q921_MULTIPLEXOR 0x52 |
|||
#define CDC_PROTOCOL_V42 0x90 |
|||
#define CDC_PROTOCOL_EURO_ISDN 0x91 |
|||
#define CDC_PROTOCOL_V24_RATE_ADAPTATION 0x92 |
|||
#define CDC_PROTOCOL_CAPI 0x93 |
|||
#define CDC_PROTOCOL_HOST_BASED_DRIVER 0xFD |
|||
#define CDC_PROTOCOL_DESCRIBED_IN_PUFD 0xFE |
|||
|
|||
// Type values for bDescriptorType field of functional descriptors
|
|||
// (usbcdc11.pdf, 5.2.3, Table 24)
|
|||
#define CDC_CS_INTERFACE 0x24 |
|||
#define CDC_CS_ENDPOINT 0x25 |
|||
|
|||
// Type values for bDescriptorSubtype field of functional descriptors
|
|||
// (usbcdc11.pdf, 5.2.3, Table 25)
|
|||
#define CDC_HEADER 0x00 |
|||
#define CDC_CALL_MANAGEMENT 0x01 |
|||
#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02 |
|||
#define CDC_DIRECT_LINE_MANAGEMENT 0x03 |
|||
#define CDC_TELEPHONE_RINGER 0x04 |
|||
#define CDC_REPORTING_CAPABILITIES 0x05 |
|||
#define CDC_UNION 0x06 |
|||
#define CDC_COUNTRY_SELECTION 0x07 |
|||
#define CDC_TELEPHONE_OPERATIONAL_MODES 0x08 |
|||
#define CDC_USB_TERMINAL 0x09 |
|||
#define CDC_NETWORK_CHANNEL 0x0A |
|||
#define CDC_PROTOCOL_UNIT 0x0B |
|||
#define CDC_EXTENSION_UNIT 0x0C |
|||
#define CDC_MULTI_CHANNEL_MANAGEMENT 0x0D |
|||
#define CDC_CAPI_CONTROL_MANAGEMENT 0x0E |
|||
#define CDC_ETHERNET_NETWORKING 0x0F |
|||
#define CDC_ATM_NETWORKING 0x10 |
|||
|
|||
// CDC class-specific request codes
|
|||
// (usbcdc11.pdf, 6.2, Table 46)
|
|||
// see Table 45 for info about the specific requests.
|
|||
#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 |
|||
#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 |
|||
#define CDC_SET_COMM_FEATURE 0x02 |
|||
#define CDC_GET_COMM_FEATURE 0x03 |
|||
#define CDC_CLEAR_COMM_FEATURE 0x04 |
|||
#define CDC_SET_AUX_LINE_STATE 0x10 |
|||
#define CDC_SET_HOOK_STATE 0x11 |
|||
#define CDC_PULSE_SETUP 0x12 |
|||
#define CDC_SEND_PULSE 0x13 |
|||
#define CDC_SET_PULSE_TIME 0x14 |
|||
#define CDC_RING_AUX_JACK 0x15 |
|||
#define CDC_SET_LINE_CODING 0x20 |
|||
#define CDC_GET_LINE_CODING 0x21 |
|||
#define CDC_SET_CONTROL_LINE_STATE 0x22 |
|||
#define CDC_SEND_BREAK 0x23 |
|||
#define CDC_SET_RINGER_PARMS 0x30 |
|||
#define CDC_GET_RINGER_PARMS 0x31 |
|||
#define CDC_SET_OPERATION_PARMS 0x32 |
|||
#define CDC_GET_OPERATION_PARMS 0x33 |
|||
#define CDC_SET_LINE_PARMS 0x34 |
|||
#define CDC_GET_LINE_PARMS 0x35 |
|||
#define CDC_DIAL_DIGITS 0x36 |
|||
#define CDC_SET_UNIT_PARAMETER 0x37 |
|||
#define CDC_GET_UNIT_PARAMETER 0x38 |
|||
#define CDC_CLEAR_UNIT_PARAMETER 0x39 |
|||
#define CDC_GET_PROFILE 0x3A |
|||
#define CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40 |
|||
#define CDC_SET_ETHERNET_PMP_FILTER 0x41 |
|||
#define CDC_GET_ETHERNET_PMP_FILTER 0x42 |
|||
#define CDC_SET_ETHERNET_PACKET_FILTER 0x43 |
|||
#define CDC_GET_ETHERNET_STATISTIC 0x44 |
|||
#define CDC_SET_ATM_DATA_FORMAT 0x50 |
|||
#define CDC_GET_ATM_DEVICE_STATISTICS 0x51 |
|||
#define CDC_SET_ATM_DEFAULT_VC 0x52 |
|||
#define CDC_GET_ATM_VC_STATISTICS 0x53 |
|||
|
|||
// Communication feature selector codes
|
|||
// (usbcdc11.pdf, 6.2.2..6.2.4, Table 47)
|
|||
#define CDC_ABSTRACT_STATE 0x01 |
|||
#define CDC_COUNTRY_SETTING 0x02 |
|||
|
|||
// Feature Status returned for ABSTRACT_STATE Selector
|
|||
// (usbcdc11.pdf, 6.2.3, Table 48)
|
|||
#define CDC_IDLE_SETTING (1 << 0) |
|||
#define CDC_DATA_MULTPLEXED_STATE (1 << 1) |
|||
|
|||
|
|||
// Control signal bitmap values for the SetControlLineState request
|
|||
// (usbcdc11.pdf, 6.2.14, Table 51)
|
|||
#define CDC_DTE_PRESENT (1 << 0) |
|||
#define CDC_ACTIVATE_CARRIER (1 << 1) |
|||
|
|||
// CDC class-specific notification codes
|
|||
// (usbcdc11.pdf, 6.3, Table 68)
|
|||
// see Table 67 for Info about class-specific notifications
|
|||
#define CDC_NOTIFICATION_NETWORK_CONNECTION 0x00 |
|||
#define CDC_RESPONSE_AVAILABLE 0x01 |
|||
#define CDC_AUX_JACK_HOOK_STATE 0x08 |
|||
#define CDC_RING_DETECT 0x09 |
|||
#define CDC_NOTIFICATION_SERIAL_STATE 0x20 |
|||
#define CDC_CALL_STATE_CHANGE 0x28 |
|||
#define CDC_LINE_STATE_CHANGE 0x29 |
|||
#define CDC_CONNECTION_SPEED_CHANGE 0x2A |
|||
|
|||
// UART state bitmap values (Serial state notification).
|
|||
// (usbcdc11.pdf, 6.3.5, Table 69)
|
|||
#define CDC_SERIAL_STATE_OVERRUN (1 << 6) // receive data overrun error has occurred
|
|||
#define CDC_SERIAL_STATE_PARITY (1 << 5) // parity error has occurred
|
|||
#define CDC_SERIAL_STATE_FRAMING (1 << 4) // framing error has occurred
|
|||
#define CDC_SERIAL_STATE_RING (1 << 3) // state of ring signal detection
|
|||
#define CDC_SERIAL_STATE_BREAK (1 << 2) // state of break detection
|
|||
#define CDC_SERIAL_STATE_TX_CARRIER (1 << 1) // state of transmission carrier
|
|||
#define CDC_SERIAL_STATE_RX_CARRIER (1 << 0) // state of receiver carrier
|
|||
|
|||
// capabilities callmgmt
|
|||
#define CDC_CALLMGMT_CAP_CALLMGMT 0x01 |
|||
#define CDC_CALLMGMT_CAP_DATAINTF 0x02 |
|||
|
|||
// capabilities acm
|
|||
#define CDC_ACM_CAP_COMM 0x01 |
|||
#define CDC_ACM_CAP_LINE 0x02 |
|||
#define CDC_ACM_CAP_BRK 0x04 |
|||
#define CDC_ACM_CAP_NOTIFY 0x08 |
|||
|
|||
|
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
* Structures based on usbcdc11.pdf (www.usb.org) |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
// Header functional descriptor
|
|||
// (usbcdc11.pdf, 5.2.3.1)
|
|||
// This header must precede any list of class-specific descriptors.
|
|||
typedef struct __packed _CDC_HEADER_DESCRIPTOR{ |
|||
uint8_t bFunctionLength; // size of this descriptor in bytes
|
|||
uint8_t bDescriptorType; // CS_INTERFACE descriptor type
|
|||
uint8_t bDescriptorSubtype; // Header functional descriptor subtype
|
|||
uint16_t bcdCDC; // USB CDC specification release version
|
|||
} CDC_HEADER_DESCRIPTOR; |
|||
|
|||
//Call management functional descriptor
|
|||
// (usbcdc11.pdf, 5.2.3.2)
|
|||
// Describes the processing of calls for the communication class interface.
|
|||
typedef struct __packed _CDC_CALL_MANAGEMENT_DESCRIPTOR{ |
|||
uint8_t bFunctionLength; // size of this descriptor in bytes
|
|||
uint8_t bDescriptorType; // CS_INTERFACE descriptor type
|
|||
uint8_t bDescriptorSubtype; // call management functional descriptor subtype
|
|||
uint8_t bmCapabilities; // capabilities that this configuration supports
|
|||
uint8_t bDataInterface; // interface number of the data class interface used for call management (optional)
|
|||
} CDC_CALL_MANAGEMENT_DESCRIPTOR; |
|||
|
|||
// Abstract control management functional descriptor
|
|||
// (usbcdc11.pdf, 5.2.3.3)
|
|||
// Describes the command supported by the communication interface class with the Abstract Control Model subclass code.
|
|||
typedef struct __packed _CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR{ |
|||
uint8_t bFunctionLength; // size of this descriptor in bytes
|
|||
uint8_t bDescriptorType; // CS_INTERFACE descriptor type
|
|||
uint8_t bDescriptorSubtype; // abstract control management functional descriptor subtype
|
|||
uint8_t bmCapabilities; // capabilities supported by this configuration
|
|||
} CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR; |
|||
|
|||
// Union functional descriptors
|
|||
// (usbcdc11.pdf, 5.2.3.8)
|
|||
// Describes the relationship between a group of interfaces that can be considered to form a functional unit.
|
|||
typedef struct __packed _CDC_UNION_DESCRIPTOR{ |
|||
uint8_t bFunctionLength; // size of this descriptor in bytes
|
|||
uint8_t bDescriptorType; // CS_INTERFACE descriptor type
|
|||
uint8_t bDescriptorSubtype; // union functional descriptor subtype
|
|||
uint8_t bMasterInterface; // interface number designated as master
|
|||
} CDC_UNION_DESCRIPTOR; |
|||
|
|||
// Union functional descriptors with one slave interface
|
|||
// (usbcdc11.pdf, 5.2.3.8)
|
|||
typedef struct __packed _CDC_UNION_1SLAVE_DESCRIPTOR{ |
|||
CDC_UNION_DESCRIPTOR sUnion; // Union functional descriptor
|
|||
uint8_t bSlaveInterfaces[1]; // Slave interface 0
|
|||
} CDC_UNION_1SLAVE_DESCRIPTOR; |
|||
|
|||
// Line coding structure
|
|||
// Format of the data returned when a GetLineCoding request is received
|
|||
// (usbcdc11.pdf, 6.2.13)
|
|||
typedef struct __packed _CDC_LINE_CODING{ |
|||
uint32_t dwDTERate; // Data terminal rate in bits per second
|
|||
uint8_t bCharFormat; // Number of stop bits
|
|||
uint8_t bParityType; // Parity bit type
|
|||
uint8_t bDataBits; // Number of data bits
|
|||
} CDC_LINE_CODING; |
|||
|
|||
// Notification header
|
|||
// Data sent on the notification endpoint must follow this header.
|
|||
// see USB_SETUP_PACKET in file usb.h
|
|||
typedef USB_SETUP_PACKET CDC_NOTIFICATION_HEADER; |
|||
|
|||
#endif /* __CDC_H */ |
|||
|
@ -0,0 +1,258 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: cdcuser.c |
|||
* Purpose: USB Communication Device Class User module |
|||
* Version: V1.10 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC microcontroller devices only. Nothing else |
|||
* gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
extern "C" { |
|||
#include <lpc_types.h> |
|||
#include <debug_frmwrk.h> |
|||
} |
|||
|
|||
#include "usb.h" |
|||
#include "usbhw.h" |
|||
#include "usbcfg.h" |
|||
#include "usbcore.h" |
|||
#include "cdc.h" |
|||
#include "cdcuser.h" |
|||
|
|||
#include <HAL_LPC1768/serial.h> |
|||
|
|||
unsigned char BulkBufIn[USB_CDC_BUFSIZE]; // Buffer to store USB IN packet
|
|||
unsigned char BulkBufOut[USB_CDC_BUFSIZE]; // Buffer to store USB OUT packet
|
|||
unsigned char NotificationBuf[10]; |
|||
|
|||
CDC_LINE_CODING CDC_LineCoding = { 921600, 0, 0, 8 }; |
|||
unsigned short CDC_DepInEmpty = 1; // Data IN EP is empty
|
|||
unsigned short CDC_LineState = 0; |
|||
unsigned short CDC_SerialState = 0; |
|||
|
|||
|
|||
extern HalSerial usb_serial; |
|||
/*----------------------------------------------------------------------------
|
|||
write data to CDC_OutBuf |
|||
*---------------------------------------------------------------------------*/ |
|||
uint32_t CDC_WrOutBuf(const char *buffer, uint32_t *length) { |
|||
uint32_t bytesToWrite, bytesWritten; |
|||
|
|||
// Write *length bytes
|
|||
bytesToWrite = *length; |
|||
bytesWritten = bytesToWrite; |
|||
|
|||
while (bytesToWrite) { |
|||
usb_serial.receive_buffer.write(*buffer++); // Copy Data to buffer
|
|||
bytesToWrite--; |
|||
} |
|||
|
|||
return (bytesWritten); |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
check if character(s) are available at CDC_OutBuf |
|||
*---------------------------------------------------------------------------*/ |
|||
uint32_t CDC_OutBufAvailChar(uint32_t *availChar) { |
|||
*availChar = usb_serial.transmit_buffer.available(); |
|||
return (0); |
|||
} |
|||
/* end Buffer handling */ |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
CDC Initialisation |
|||
Initializes the data structures and serial port |
|||
Parameters: None |
|||
Return Value: None |
|||
*---------------------------------------------------------------------------*/ |
|||
void CDC_Init() { |
|||
CDC_DepInEmpty = 1; |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
CDC SendEncapsulatedCommand Request Callback |
|||
Called automatically on CDC SEND_ENCAPSULATED_COMMAND Request |
|||
Parameters: None (global SetupPacket and EP0Buf) |
|||
Return Value: TRUE - Success, FALSE - Error |
|||
*---------------------------------------------------------------------------*/ |
|||
uint32_t CDC_SendEncapsulatedCommand(void) { |
|||
|
|||
return (TRUE); |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
CDC GetEncapsulatedResponse Request Callback |
|||
Called automatically on CDC Get_ENCAPSULATED_RESPONSE Request |
|||
Parameters: None (global SetupPacket and EP0Buf) |
|||
Return Value: TRUE - Success, FALSE - Error |
|||
*---------------------------------------------------------------------------*/ |
|||
uint32_t CDC_GetEncapsulatedResponse(void) { |
|||
|
|||
/* ... add code to handle request */ |
|||
return (TRUE); |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
CDC SetCommFeature Request Callback |
|||
Called automatically on CDC Set_COMM_FATURE Request |
|||
Parameters: FeatureSelector |
|||
Return Value: TRUE - Success, FALSE - Error |
|||
*---------------------------------------------------------------------------*/ |
|||
uint32_t CDC_SetCommFeature(unsigned short wFeatureSelector) { |
|||
|
|||
/* ... add code to handle request */ |
|||
return (TRUE); |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
CDC GetCommFeature Request Callback |
|||
Called automatically on CDC Get_COMM_FATURE Request |
|||
Parameters: FeatureSelector |
|||
Return Value: TRUE - Success, FALSE - Error |
|||
*---------------------------------------------------------------------------*/ |
|||
uint32_t CDC_GetCommFeature(unsigned short wFeatureSelector) { |
|||
|
|||
/* ... add code to handle request */ |
|||
return (TRUE); |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
CDC ClearCommFeature Request Callback |
|||
Called automatically on CDC CLEAR_COMM_FATURE Request |
|||
Parameters: FeatureSelector |
|||
Return Value: TRUE - Success, FALSE - Error |
|||
*---------------------------------------------------------------------------*/ |
|||
uint32_t CDC_ClearCommFeature(unsigned short wFeatureSelector) { |
|||
|
|||
/* ... add code to handle request */ |
|||
return (TRUE); |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
CDC SetLineCoding Request Callback |
|||
Called automatically on CDC SET_LINE_CODING Request |
|||
Parameters: none (global SetupPacket and EP0Buf) |
|||
Return Value: TRUE - Success, FALSE - Error |
|||
*---------------------------------------------------------------------------*/ |
|||
uint32_t CDC_SetLineCoding(void) { |
|||
|
|||
CDC_LineCoding.dwDTERate = (EP0Buf[0] << 0) | (EP0Buf[1] << 8) | (EP0Buf[2] << 16) | (EP0Buf[3] << 24); |
|||
CDC_LineCoding.bCharFormat = EP0Buf[4]; |
|||
CDC_LineCoding.bParityType = EP0Buf[5]; |
|||
CDC_LineCoding.bDataBits = EP0Buf[6]; |
|||
|
|||
return (TRUE); |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
CDC GetLineCoding Request Callback |
|||
Called automatically on CDC GET_LINE_CODING Request |
|||
Parameters: None (global SetupPacket and EP0Buf) |
|||
Return Value: TRUE - Success, FALSE - Error |
|||
*---------------------------------------------------------------------------*/ |
|||
uint32_t CDC_GetLineCoding(void) { |
|||
|
|||
EP0Buf[0] = (CDC_LineCoding.dwDTERate >> 0) & 0xFF; |
|||
EP0Buf[1] = (CDC_LineCoding.dwDTERate >> 8) & 0xFF; |
|||
EP0Buf[2] = (CDC_LineCoding.dwDTERate >> 16) & 0xFF; |
|||
EP0Buf[3] = (CDC_LineCoding.dwDTERate >> 24) & 0xFF; |
|||
EP0Buf[4] = CDC_LineCoding.bCharFormat; |
|||
EP0Buf[5] = CDC_LineCoding.bParityType; |
|||
EP0Buf[6] = CDC_LineCoding.bDataBits; |
|||
|
|||
return (TRUE); |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
CDC SetControlLineState Request Callback |
|||
Called automatically on CDC SET_CONTROL_LINE_STATE Request |
|||
Parameters: ControlSignalBitmap |
|||
Return Value: TRUE - Success, FALSE - Error |
|||
*---------------------------------------------------------------------------*/ |
|||
uint32_t CDC_SetControlLineState(unsigned short wControlSignalBitmap) { |
|||
CDC_LineState = wControlSignalBitmap; |
|||
usb_serial.host_connected = wControlSignalBitmap > 0 ? true : false; |
|||
return true; |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
CDC SendBreak Request Callback |
|||
Called automatically on CDC Set_COMM_FATURE Request |
|||
Parameters: 0xFFFF start of Break |
|||
0x0000 stop of Break |
|||
0x#### Duration of Break |
|||
Return Value: TRUE - Success, FALSE - Error |
|||
*---------------------------------------------------------------------------*/ |
|||
uint32_t CDC_SendBreak(unsigned short wDurationOfBreak) { |
|||
|
|||
/* ... add code to handle request */ |
|||
return (TRUE); |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
CDC_BulkIn call on DataIn Request |
|||
Parameters: none |
|||
Return Value: none |
|||
*---------------------------------------------------------------------------*/ |
|||
void CDC_BulkIn(void) { |
|||
uint32_t numBytesAvail = usb_serial.transmit_buffer.available(); |
|||
|
|||
if (numBytesAvail > 0) { |
|||
numBytesAvail = numBytesAvail > (USB_CDC_BUFSIZE - 1) ? (USB_CDC_BUFSIZE - 1) : numBytesAvail; |
|||
for(uint32_t i = 0; i < numBytesAvail; ++i) { |
|||
BulkBufIn[i] = usb_serial.transmit_buffer.read(); //todo: optimise
|
|||
} |
|||
USB_WriteEP(CDC_DEP_IN, &BulkBufIn[0], numBytesAvail); |
|||
} else { |
|||
CDC_DepInEmpty = 1; |
|||
} |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
CDC_BulkOut call on DataOut Request |
|||
Parameters: none |
|||
Return Value: none |
|||
*---------------------------------------------------------------------------*/ |
|||
void CDC_BulkOut(void) { |
|||
uint32_t numBytesRead = USB_ReadEP(CDC_DEP_OUT, &BulkBufOut[0]); |
|||
CDC_WrOutBuf((char *) &BulkBufOut[0], &numBytesRead); |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
Get the SERIAL_STATE as defined in usbcdc11.pdf, 6.3.5, Table 69. |
|||
Parameters: none |
|||
Return Value: SerialState as defined in usbcdc11.pdf |
|||
*---------------------------------------------------------------------------*/ |
|||
unsigned short CDC_GetSerialState(void) { |
|||
CDC_SerialState = CDC_LineState; |
|||
//todo: detect buffer overrun
|
|||
return (CDC_SerialState); |
|||
} |
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
Send the SERIAL_STATE notification as defined in usbcdc11.pdf, 6.3.5. |
|||
*---------------------------------------------------------------------------*/ |
|||
void CDC_NotificationIn(void) { |
|||
|
|||
NotificationBuf[0] = 0xA1; // bmRequestType
|
|||
NotificationBuf[1] = CDC_NOTIFICATION_SERIAL_STATE; // bNotification (SERIAL_STATE)
|
|||
NotificationBuf[2] = 0x00; // wValue
|
|||
NotificationBuf[3] = 0x00; |
|||
NotificationBuf[4] = 0x00; // wIndex (Interface #, LSB first)
|
|||
NotificationBuf[5] = 0x00; |
|||
NotificationBuf[6] = 0x02; // wLength (Data length = 2 bytes, LSB first)
|
|||
NotificationBuf[7] = 0x00; |
|||
NotificationBuf[8] = (CDC_SerialState >> 0) & 0xFF; // UART State Bitmap (16bits, LSB first)
|
|||
NotificationBuf[9] = (CDC_SerialState >> 8) & 0xFF; |
|||
|
|||
USB_WriteEP(CDC_CEP_IN, &NotificationBuf[0], 10); // send notification
|
|||
} |
@ -0,0 +1,62 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: cdcuser.h |
|||
* Purpose: USB Communication Device Class User module Definitions |
|||
* Version: V1.10 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC microcontroller devices only. Nothing else |
|||
* gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
#ifndef __CDCUSER_H__ |
|||
#define __CDCUSER_H__ |
|||
|
|||
/* CDC buffer handling */ |
|||
extern uint32_t CDC_RdOutBuf(char *buffer, const uint32_t *length); |
|||
extern uint32_t CDC_WrOutBuf(const char *buffer, uint32_t *length); |
|||
extern uint32_t CDC_OutBufAvailChar(uint32_t *availChar); |
|||
|
|||
/* CDC Data In/Out Endpoint Address */ |
|||
#define CDC_DEP_IN 0x82 |
|||
#define CDC_DEP_OUT 0x02 |
|||
|
|||
/* CDC Communication In Endpoint Address */ |
|||
#define CDC_CEP_IN 0x81 |
|||
|
|||
/* CDC Requests Callback Functions */ |
|||
extern uint32_t CDC_SendEncapsulatedCommand(void); |
|||
extern uint32_t CDC_GetEncapsulatedResponse(void); |
|||
extern uint32_t CDC_SetCommFeature(unsigned short wFeatureSelector); |
|||
extern uint32_t CDC_GetCommFeature(unsigned short wFeatureSelector); |
|||
extern uint32_t CDC_ClearCommFeature(unsigned short wFeatureSelector); |
|||
extern uint32_t CDC_GetLineCoding(void); |
|||
extern uint32_t CDC_SetLineCoding(void); |
|||
extern uint32_t CDC_SetControlLineState(unsigned short wControlSignalBitmap); |
|||
extern uint32_t CDC_SendBreak(unsigned short wDurationOfBreak); |
|||
|
|||
/* CDC Bulk Callback Functions */ |
|||
extern void CDC_BulkIn(void); |
|||
extern void CDC_BulkOut(void); |
|||
|
|||
/* CDC Notification Callback Function */ |
|||
extern void CDC_NotificationIn(void); |
|||
|
|||
/* CDC Initializtion Function */ |
|||
extern void CDC_Init(); |
|||
|
|||
/* CDC prepare the SERAIAL_STATE */ |
|||
extern unsigned short CDC_GetSerialState(void); |
|||
|
|||
/* flow control */ |
|||
extern unsigned short CDC_DepInEmpty; // DataEndPoint IN empty
|
|||
|
|||
#endif /* __CDCUSER_H__ */ |
|||
|
@ -0,0 +1,116 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: MSC.H |
|||
* Purpose: USB Mass Storage Class Definitions |
|||
* Version: V1.10 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC family microcontroller devices only. Nothing |
|||
* else gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2005-2009 Keil Software. |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
#ifndef __MSC_H__ |
|||
#define __MSC_H__ |
|||
|
|||
|
|||
#if defined ( __GNUC__ ) |
|||
#define __packed __attribute__((__packed__)) |
|||
#endif |
|||
|
|||
|
|||
/* MSC Subclass Codes */ |
|||
#define MSC_SUBCLASS_RBC 0x01 |
|||
#define MSC_SUBCLASS_SFF8020I_MMC2 0x02 |
|||
#define MSC_SUBCLASS_QIC157 0x03 |
|||
#define MSC_SUBCLASS_UFI 0x04 |
|||
#define MSC_SUBCLASS_SFF8070I 0x05 |
|||
#define MSC_SUBCLASS_SCSI 0x06 |
|||
|
|||
/* MSC Protocol Codes */ |
|||
#define MSC_PROTOCOL_CBI_INT 0x00 |
|||
#define MSC_PROTOCOL_CBI_NOINT 0x01 |
|||
#define MSC_PROTOCOL_BULK_ONLY 0x50 |
|||
|
|||
|
|||
/* MSC Request Codes */ |
|||
#define MSC_REQUEST_RESET 0xFF |
|||
#define MSC_REQUEST_GET_MAX_LUN 0xFE |
|||
|
|||
|
|||
/* MSC Bulk-only Stage */ |
|||
#define MSC_BS_CBW 0 /* Command Block Wrapper */ |
|||
#define MSC_BS_DATA_OUT 1 /* Data Out Phase */ |
|||
#define MSC_BS_DATA_IN 2 /* Data In Phase */ |
|||
#define MSC_BS_DATA_IN_LAST 3 /* Data In Last Phase */ |
|||
#define MSC_BS_DATA_IN_LAST_STALL 4 /* Data In Last Phase with Stall */ |
|||
#define MSC_BS_CSW 5 /* Command Status Wrapper */ |
|||
#define MSC_BS_ERROR 6 /* Error */ |
|||
|
|||
|
|||
/* Bulk-only Command Block Wrapper */ |
|||
#if defined ( __CC_ARM ) |
|||
typedef __packed struct _MSC_CBW { |
|||
#elif defined ( __GNUC__ ) |
|||
typedef struct __packed _MSC_CBW { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
typedef __packed struct _MSC_CBW { |
|||
#endif |
|||
uint32_t dSignature; |
|||
uint32_t dTag; |
|||
uint32_t dDataLength; |
|||
uint8_t bmFlags; |
|||
uint8_t bLUN; |
|||
uint8_t bCBLength; |
|||
uint8_t CB[16]; |
|||
} MSC_CBW; |
|||
|
|||
/* Bulk-only Command Status Wrapper */ |
|||
#if defined ( __CC_ARM ) |
|||
typedef __packed struct _MSC_CSW { |
|||
#elif defined ( __GNUC__ ) |
|||
typedef struct __packed _MSC_CSW { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
typedef __packed struct _MSC_CSW { |
|||
#endif |
|||
uint32_t dSignature; |
|||
uint32_t dTag; |
|||
uint32_t dDataResidue; |
|||
uint8_t bStatus; |
|||
} MSC_CSW; |
|||
|
|||
#define MSC_CBW_Signature 0x43425355 |
|||
#define MSC_CSW_Signature 0x53425355 |
|||
|
|||
|
|||
/* CSW Status Definitions */ |
|||
#define CSW_CMD_PASSED 0x00 |
|||
#define CSW_CMD_FAILED 0x01 |
|||
#define CSW_PHASE_ERROR 0x02 |
|||
|
|||
|
|||
/* SCSI Commands */ |
|||
#define SCSI_TEST_UNIT_READY 0x00 |
|||
#define SCSI_REQUEST_SENSE 0x03 |
|||
#define SCSI_FORMAT_UNIT 0x04 |
|||
#define SCSI_INQUIRY 0x12 |
|||
#define SCSI_MODE_SELECT6 0x15 |
|||
#define SCSI_MODE_SENSE6 0x1A |
|||
#define SCSI_START_STOP_UNIT 0x1B |
|||
#define SCSI_MEDIA_REMOVAL 0x1E |
|||
#define SCSI_READ_FORMAT_CAPACITIES 0x23 |
|||
#define SCSI_READ_CAPACITY 0x25 |
|||
#define SCSI_READ10 0x28 |
|||
#define SCSI_WRITE10 0x2A |
|||
#define SCSI_VERIFY10 0x2F |
|||
#define SCSI_MODE_SELECT10 0x55 |
|||
#define SCSI_MODE_SENSE10 0x5A |
|||
|
|||
|
|||
#endif /* __MSC_H__ */ |
@ -0,0 +1,716 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: MSCUSER.C |
|||
* Purpose: Mass Storage Class Custom User Module |
|||
* Version: V1.10 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC family microcontroller devices only. Nothing |
|||
* else gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2005-2009 Keil Software. |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
extern "C" { |
|||
#include "LPC17xx.h" |
|||
#include "lpc_types.h" |
|||
} |
|||
#include "usb.h" |
|||
#include "msc.h" |
|||
#include "usbcfg.h" |
|||
#include "usbhw.h" |
|||
#include "usbcore.h" |
|||
#include "mscuser.h" |
|||
|
|||
#include "../chanfs/diskio.h" |
|||
#include <debug_frmwrk.h> |
|||
|
|||
DWORD MSC_BlockCount = 0; |
|||
|
|||
uint32_t MemOK; /* Memory OK */ |
|||
|
|||
DWORD lba; /* start block */ |
|||
DWORD transfer_count; /* blocks to transfer */ |
|||
DWORD length; |
|||
uint32_t block_offset; /* current block offset*/ |
|||
|
|||
uint8_t BulkStage; /* Bulk Stage */ |
|||
|
|||
uint8_t BulkBuf[MSC_MAX_PACKET]; /* Bulk In/Out Buffer */ |
|||
uint8_t block_cache[MSC_BLOCK_SIZE]; |
|||
uint8_t BulkLen; /* Bulk In/Out Length */ |
|||
|
|||
MSC_CBW CBW; /* Command Block Wrapper */ |
|||
MSC_CSW CSW; /* Command Status Wrapper */ |
|||
uint8_t media_lock = 0; |
|||
|
|||
uint32_t MSC_SD_Lock() { |
|||
media_lock = CBW.CB[4]; //0x1 - lock, 0x0 - unlock
|
|||
// logical_unit = CBW.CB[1] & 0xE0;
|
|||
CSW.bStatus = CSW_CMD_PASSED; |
|||
MSC_SetCSW(); |
|||
return 0; |
|||
} |
|||
|
|||
uint32_t MSC_SD_Release(uint8_t pdrv) { |
|||
MSC_BlockCount = 0; |
|||
return 0; |
|||
} |
|||
|
|||
uint32_t MSC_SD_Init(uint8_t pdrv) { |
|||
DSTATUS ret = disk_initialize(pdrv); |
|||
if(ret) return ret; |
|||
if(disk_ioctl (pdrv, GET_SECTOR_COUNT, (void *)(&MSC_BlockCount))) return 1; |
|||
return 0; |
|||
} |
|||
|
|||
#define STARTSTOP_STOPMOTOR 0x0 |
|||
#define STARTSTOP_STARTMOTOR 0x1 |
|||
#define STARTSTOP_EJECT 0x2 |
|||
#define STARTSTOP_LOAD 0x3 |
|||
|
|||
void MSC_StartStopUnit() { |
|||
switch (CBW.CB[4] & 0x03) { |
|||
case STARTSTOP_EJECT: |
|||
MSC_SD_Release(0); |
|||
break; |
|||
case STARTSTOP_LOAD: |
|||
if(MSC_BlockCount == 0) { |
|||
if(MSC_SD_Init(0) != 0) { |
|||
CSW.bStatus = CSW_CMD_FAILED; |
|||
MSC_SetCSW(); |
|||
return; |
|||
} |
|||
} |
|||
break; |
|||
default: |
|||
_DBG("MSC_StartStopUnit unknown startstopunit sub command\n"); |
|||
} |
|||
CSW.bStatus = CSW_CMD_PASSED; |
|||
MSC_SetCSW(); |
|||
} |
|||
|
|||
/*
|
|||
* MSC Mass Storage Reset Request Callback |
|||
* Called automatically on Mass Storage Reset Request |
|||
* Parameters: None (global SetupPacket and EP0Buf) |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
|
|||
uint32_t MSC_Reset (void) { |
|||
BulkStage = MSC_BS_CBW; |
|||
return (TRUE); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC Get Max LUN Request Callback |
|||
* Called automatically on Get Max LUN Request |
|||
* Parameters: None (global SetupPacket and EP0Buf) |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
|
|||
uint32_t MSC_GetMaxLUN (void) { |
|||
|
|||
EP0Buf[0] = 0; /* No LUN associated with this device */ |
|||
return (TRUE); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC Memory Read Callback |
|||
* Called automatically on Memory Read Event |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_MemoryRead (void) { |
|||
uint32_t n = (length > MSC_MAX_PACKET) ? MSC_MAX_PACKET : length; |
|||
|
|||
if (lba > MSC_BlockCount) { |
|||
n = (MSC_BlockCount - lba) * MSC_BLOCK_SIZE + block_offset; |
|||
BulkStage = MSC_BS_ERROR; |
|||
} |
|||
|
|||
if(block_offset == 0) { |
|||
disk_read (0, block_cache, lba, 1); |
|||
} |
|||
|
|||
USB_WriteEP(MSC_EP_IN, &block_cache[block_offset], n); |
|||
|
|||
block_offset += n; |
|||
length -= n; |
|||
CSW.dDataResidue -= n; |
|||
|
|||
if(block_offset >= MSC_BLOCK_SIZE) { |
|||
block_offset = 0; |
|||
++lba; |
|||
} |
|||
|
|||
if (length == 0) { |
|||
BulkStage = MSC_BS_DATA_IN_LAST; |
|||
} |
|||
|
|||
if (BulkStage != MSC_BS_DATA_IN) { |
|||
CSW.bStatus = CSW_CMD_PASSED; |
|||
} |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC Memory Write Callback |
|||
* Called automatically on Memory Write Event |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_MemoryWrite (void) { |
|||
|
|||
for (uint32_t n = 0; n < BulkLen; n++) { |
|||
block_cache[block_offset + n] = BulkBuf[n]; |
|||
} |
|||
|
|||
if(block_offset + BulkLen >= MSC_BLOCK_SIZE) { |
|||
if(!(disk_status(0) & STA_PROTECT)){ |
|||
disk_write(0, block_cache, lba, 1); |
|||
} |
|||
} |
|||
|
|||
block_offset += BulkLen; |
|||
length -= BulkLen; |
|||
CSW.dDataResidue -= BulkLen; |
|||
|
|||
if(block_offset >= MSC_BLOCK_SIZE) { |
|||
block_offset = 0; |
|||
++lba; |
|||
} |
|||
|
|||
if ((length == 0) || (BulkStage == MSC_BS_CSW)) { |
|||
CSW.bStatus = CSW_CMD_PASSED; |
|||
MSC_SetCSW(); |
|||
} |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC Memory Verify Callback |
|||
* Called automatically on Memory Verify Event |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_MemoryVerify (void) { |
|||
|
|||
if(!block_offset) { |
|||
disk_read(0, block_cache, lba, 1); |
|||
} |
|||
|
|||
for (uint32_t n = 0; n < BulkLen; n++) { |
|||
if (block_cache[block_offset + n] != BulkBuf[n]) { |
|||
MemOK = FALSE; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
block_offset += BulkLen; |
|||
length -= BulkLen; |
|||
CSW.dDataResidue -= BulkLen; |
|||
|
|||
if ((length == 0) || (BulkStage == MSC_BS_CSW)) { |
|||
CSW.bStatus = (MemOK) ? CSW_CMD_PASSED : CSW_CMD_FAILED; |
|||
MSC_SetCSW(); |
|||
} |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC SCSI Read/Write Setup Callback |
|||
* Parameters: None (global variables) |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
|
|||
uint32_t MSC_RWSetup (void) { |
|||
uint32_t n; |
|||
|
|||
/* Logical Block Address of First Block */ |
|||
lba = (CBW.CB[2] << 24) | |
|||
(CBW.CB[3] << 16) | |
|||
(CBW.CB[4] << 8) | |
|||
(CBW.CB[5] << 0); |
|||
|
|||
/* Number of Blocks to transfer */ |
|||
transfer_count = (CBW.CB[7] << 8) | |
|||
(CBW.CB[8] << 0); |
|||
|
|||
block_offset = 0; |
|||
length = transfer_count * MSC_BLOCK_SIZE; |
|||
|
|||
if (CBW.dDataLength != (transfer_count * MSC_BLOCK_SIZE)) { |
|||
USB_SetStallEP(MSC_EP_IN); |
|||
USB_SetStallEP(MSC_EP_OUT); |
|||
CSW.bStatus = CSW_PHASE_ERROR; |
|||
MSC_SetCSW(); |
|||
return (FALSE); |
|||
} |
|||
|
|||
return (TRUE); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Check Data IN Format |
|||
* Parameters: None (global variables) |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
|
|||
uint32_t DataInFormat (void) { |
|||
|
|||
if (CBW.dDataLength == 0) { |
|||
CSW.bStatus = CSW_PHASE_ERROR; |
|||
MSC_SetCSW(); |
|||
return (FALSE); |
|||
} |
|||
if ((CBW.bmFlags & 0x80) == 0) { |
|||
USB_SetStallEP(MSC_EP_OUT); |
|||
CSW.bStatus = CSW_PHASE_ERROR; |
|||
MSC_SetCSW(); |
|||
return (FALSE); |
|||
} |
|||
return (TRUE); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Perform Data IN Transfer |
|||
* Parameters: None (global variables) |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
|
|||
void DataInTransfer (void) { |
|||
|
|||
if (BulkLen > CBW.dDataLength) { |
|||
BulkLen = CBW.dDataLength; |
|||
} |
|||
|
|||
USB_WriteEP(MSC_EP_IN, BulkBuf, BulkLen); |
|||
BulkStage = MSC_BS_DATA_IN_LAST; |
|||
|
|||
CSW.dDataResidue -= BulkLen; |
|||
CSW.bStatus = CSW_CMD_PASSED; |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC SCSI Test Unit Ready Callback |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_TestUnitReady (void) { |
|||
|
|||
if (CBW.dDataLength != 0) { |
|||
if ((CBW.bmFlags & 0x80) != 0) { |
|||
USB_SetStallEP(MSC_EP_IN); |
|||
} else { |
|||
USB_SetStallEP(MSC_EP_OUT); |
|||
} |
|||
} |
|||
|
|||
if(MSC_BlockCount > 0) { |
|||
CSW.bStatus = CSW_CMD_PASSED; |
|||
} else { |
|||
CSW.bStatus = CSW_CMD_FAILED; |
|||
} |
|||
|
|||
MSC_SetCSW(); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC SCSI Request Sense Callback |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_RequestSense (void) { |
|||
|
|||
if (!DataInFormat()) return; |
|||
|
|||
BulkBuf[ 0] = 0x70; /* Response Code */ |
|||
BulkBuf[ 1] = 0x00; |
|||
BulkBuf[ 2] = static_cast<uint8_t>(Sense_KEY::ILLEGAL_REQUEST); |
|||
BulkBuf[ 3] = 0x00; |
|||
BulkBuf[ 4] = 0x00; |
|||
BulkBuf[ 5] = 0x00; |
|||
BulkBuf[ 6] = 0x00; |
|||
BulkBuf[ 7] = 0x0A; /* Additional Length */ |
|||
|
|||
BulkBuf[ 8] = 0x00; |
|||
BulkBuf[ 9] = 0x00; |
|||
BulkBuf[10] = 0x00; |
|||
BulkBuf[11] = 0x00; |
|||
BulkBuf[12] = static_cast<uint8_t>(Sense_ASC::CANNOT_READ_MEDIUM); |
|||
BulkBuf[13] = static_cast<uint8_t>(Sense_ASCQ::UNKNOWN_FORMAT); |
|||
BulkBuf[14] = 0x00; |
|||
BulkBuf[15] = 0x00; |
|||
BulkBuf[16] = 0x00; |
|||
BulkBuf[17] = 0x00; |
|||
|
|||
if (MSC_BlockCount == 0) { |
|||
BulkBuf[ 2] = static_cast<uint8_t>(Sense_KEY::NOT_READY); |
|||
BulkBuf[12] = static_cast<uint8_t>(Sense_ASC::MEDIUM_NOT_PRESENT); |
|||
BulkBuf[13] = static_cast<uint8_t>(Sense_ASCQ::LOADABLE); |
|||
} |
|||
|
|||
BulkLen = 18; |
|||
DataInTransfer(); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC SCSI Inquiry Callback |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_Inquiry (void) { |
|||
|
|||
if (!DataInFormat()) return; |
|||
|
|||
BulkBuf[ 0] = 0x00; /* Direct Access Device */ |
|||
BulkBuf[ 1] = 0x80; /* RMB = 1: Removable Medium */ |
|||
BulkBuf[ 2] = 0x00; /* Version: No conformance claim to standard */ |
|||
BulkBuf[ 3] = 0x01; |
|||
|
|||
BulkBuf[ 4] = 36-4; /* Additional Length */ |
|||
BulkBuf[ 5] = 0x80; /* SCCS = 1: Storage Controller Component */ |
|||
BulkBuf[ 6] = 0x00; |
|||
BulkBuf[ 7] = 0x00; |
|||
|
|||
BulkBuf[ 8] = 'M'; /* Vendor Identification */ |
|||
BulkBuf[ 9] = 'a'; |
|||
BulkBuf[10] = 'r'; |
|||
BulkBuf[11] = 'l'; |
|||
BulkBuf[12] = 'i'; |
|||
BulkBuf[13] = 'n'; |
|||
BulkBuf[14] = ' '; |
|||
BulkBuf[15] = ' '; |
|||
|
|||
BulkBuf[16] = 'R'; /* Product Identification */ |
|||
BulkBuf[17] = 'e'; |
|||
BulkBuf[18] = '-'; |
|||
BulkBuf[19] = 'A'; |
|||
BulkBuf[20] = 'R'; |
|||
BulkBuf[21] = 'M'; |
|||
BulkBuf[22] = ' '; |
|||
BulkBuf[23] = 'S'; |
|||
BulkBuf[24] = 'D'; |
|||
BulkBuf[25] = 'C'; |
|||
BulkBuf[26] = 'a'; |
|||
BulkBuf[27] = 'r'; |
|||
BulkBuf[28] = 'd'; |
|||
BulkBuf[29] = ' '; |
|||
BulkBuf[30] = '0'; |
|||
BulkBuf[31] = '1'; |
|||
|
|||
BulkBuf[32] = '1'; /* Product Revision Level */ |
|||
BulkBuf[33] = '.'; |
|||
BulkBuf[34] = '0'; |
|||
BulkBuf[35] = ' '; |
|||
|
|||
if(MSC_BlockCount == 0) { |
|||
BulkBuf[0] = 0x20; // Direct Access Device usually available but not currently
|
|||
} |
|||
|
|||
BulkLen = 36; |
|||
DataInTransfer(); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC SCSI Mode Sense (6-Byte) Callback |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_ModeSense6 (void) { |
|||
|
|||
if (!DataInFormat()) return; |
|||
|
|||
BulkBuf[ 0] = 0x03; |
|||
BulkBuf[ 1] = 0x00; |
|||
BulkBuf[ 2] = 0x00; |
|||
BulkBuf[ 3] = 0x00; |
|||
|
|||
BulkLen = 4; |
|||
DataInTransfer(); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC SCSI Mode Sense (10-Byte) Callback |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_ModeSense10 (void) { |
|||
|
|||
if (!DataInFormat()) return; |
|||
|
|||
BulkBuf[ 0] = 0x00; |
|||
BulkBuf[ 1] = 0x06; |
|||
BulkBuf[ 2] = 0x00; |
|||
BulkBuf[ 3] = 0x00; |
|||
BulkBuf[ 4] = 0x00; |
|||
BulkBuf[ 5] = 0x00; |
|||
BulkBuf[ 6] = 0x00; |
|||
BulkBuf[ 7] = 0x00; |
|||
|
|||
BulkLen = 8; |
|||
DataInTransfer(); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC SCSI Read Capacity Callback |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_ReadCapacity (void) { |
|||
|
|||
if (!DataInFormat()) return; |
|||
|
|||
/* Last Logical Block */ |
|||
BulkBuf[ 0] = ((MSC_BlockCount - 1) >> 24) & 0xFF; |
|||
BulkBuf[ 1] = ((MSC_BlockCount - 1) >> 16) & 0xFF; |
|||
BulkBuf[ 2] = ((MSC_BlockCount - 1) >> 8) & 0xFF; |
|||
BulkBuf[ 3] = ((MSC_BlockCount - 1) >> 0) & 0xFF; |
|||
|
|||
/* Block Length */ |
|||
BulkBuf[ 4] = (MSC_BLOCK_SIZE >> 24) & 0xFF; |
|||
BulkBuf[ 5] = (MSC_BLOCK_SIZE >> 16) & 0xFF; |
|||
BulkBuf[ 6] = (MSC_BLOCK_SIZE >> 8) & 0xFF; |
|||
BulkBuf[ 7] = (MSC_BLOCK_SIZE >> 0) & 0xFF; |
|||
|
|||
BulkLen = 8; |
|||
DataInTransfer(); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC SCSI Read Format Capacity Callback |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_ReadFormatCapacity (void) { |
|||
|
|||
if (!DataInFormat()) return; |
|||
|
|||
BulkBuf[ 0] = 0x00; |
|||
BulkBuf[ 1] = 0x00; |
|||
BulkBuf[ 2] = 0x00; |
|||
BulkBuf[ 3] = 0x08; /* Capacity List Length */ |
|||
|
|||
/* Block Count */ |
|||
BulkBuf[ 4] = (MSC_BlockCount >> 24) & 0xFF; |
|||
BulkBuf[ 5] = (MSC_BlockCount >> 16) & 0xFF; |
|||
BulkBuf[ 6] = (MSC_BlockCount >> 8) & 0xFF; |
|||
BulkBuf[ 7] = (MSC_BlockCount >> 0) & 0xFF; |
|||
|
|||
/* Block Length */ |
|||
BulkBuf[ 8] = 0x02; /* Descriptor Code: Formatted Media */ |
|||
BulkBuf[ 9] = (MSC_BLOCK_SIZE >> 16) & 0xFF; |
|||
BulkBuf[10] = (MSC_BLOCK_SIZE >> 8) & 0xFF; |
|||
BulkBuf[11] = (MSC_BLOCK_SIZE >> 0) & 0xFF; |
|||
|
|||
BulkLen = 12; |
|||
DataInTransfer(); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC Get Command Block Wrapper Callback |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_GetCBW (void) { |
|||
uint32_t n; |
|||
|
|||
for (n = 0; n < BulkLen; n++) { |
|||
*((uint8_t *)&CBW + n) = BulkBuf[n]; |
|||
} |
|||
if ((BulkLen == sizeof(CBW)) && (CBW.dSignature == MSC_CBW_Signature)) { |
|||
/* Valid CBW */ |
|||
CSW.dTag = CBW.dTag; |
|||
CSW.dDataResidue = CBW.dDataLength; |
|||
if ((CBW.bLUN != 0) || (CBW.bCBLength < 1) || CBW.bCBLength > 16) { |
|||
fail: CSW.bStatus = CSW_CMD_FAILED; |
|||
MSC_SetCSW(); |
|||
_DBG("Failed SCSI OP code "); |
|||
_DBH(CBW.CB[0]); |
|||
_DBG("\n"); |
|||
} else { |
|||
switch (CBW.CB[0]) { |
|||
case SCSI_TEST_UNIT_READY: |
|||
MSC_TestUnitReady(); |
|||
break; |
|||
case SCSI_REQUEST_SENSE: |
|||
MSC_RequestSense(); |
|||
break; |
|||
case SCSI_FORMAT_UNIT: |
|||
goto fail; |
|||
case SCSI_INQUIRY: |
|||
MSC_Inquiry(); |
|||
break; |
|||
case SCSI_START_STOP_UNIT: |
|||
MSC_StartStopUnit(); |
|||
break; |
|||
case SCSI_MEDIA_REMOVAL: |
|||
MSC_SD_Lock(); |
|||
break; |
|||
case SCSI_MODE_SELECT6: |
|||
goto fail; |
|||
case SCSI_MODE_SENSE6: |
|||
MSC_ModeSense6(); |
|||
break; |
|||
case SCSI_MODE_SELECT10: |
|||
goto fail; |
|||
case SCSI_MODE_SENSE10: |
|||
MSC_ModeSense10(); |
|||
break; |
|||
case SCSI_READ_FORMAT_CAPACITIES: |
|||
MSC_ReadFormatCapacity(); |
|||
break; |
|||
case SCSI_READ_CAPACITY: |
|||
MSC_ReadCapacity(); |
|||
break; |
|||
case SCSI_READ10: |
|||
if (MSC_RWSetup()) { |
|||
if ((CBW.bmFlags & 0x80) != 0) { |
|||
BulkStage = MSC_BS_DATA_IN; |
|||
MSC_MemoryRead(); |
|||
} else { |
|||
USB_SetStallEP(MSC_EP_OUT); |
|||
CSW.bStatus = CSW_PHASE_ERROR; |
|||
MSC_SetCSW(); |
|||
} |
|||
} |
|||
break; |
|||
case SCSI_WRITE10: |
|||
if (MSC_RWSetup()) { |
|||
if ((CBW.bmFlags & 0x80) == 0) { |
|||
BulkStage = MSC_BS_DATA_OUT; |
|||
} else { |
|||
USB_SetStallEP(MSC_EP_IN); |
|||
CSW.bStatus = CSW_PHASE_ERROR; |
|||
MSC_SetCSW(); |
|||
} |
|||
} |
|||
break; |
|||
case SCSI_VERIFY10: |
|||
if (MSC_RWSetup()) { |
|||
if ((CBW.bmFlags & 0x80) == 0) { |
|||
BulkStage = MSC_BS_DATA_OUT; |
|||
MemOK = TRUE; |
|||
} else { |
|||
USB_SetStallEP(MSC_EP_IN); |
|||
CSW.bStatus = CSW_PHASE_ERROR; |
|||
MSC_SetCSW(); |
|||
} |
|||
} |
|||
break; |
|||
default: |
|||
goto fail; |
|||
} |
|||
} |
|||
} else { |
|||
/* Invalid CBW */ |
|||
USB_SetStallEP(MSC_EP_IN); |
|||
USB_SetStallEP(MSC_EP_OUT); |
|||
BulkStage = MSC_BS_ERROR; |
|||
} |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC Set Command Status Wrapper Callback |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_SetCSW (void) { |
|||
|
|||
CSW.dSignature = MSC_CSW_Signature; |
|||
USB_WriteEP(MSC_EP_IN, (uint8_t *)&CSW, sizeof(CSW)); |
|||
BulkStage = MSC_BS_CSW; |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC Bulk In Callback |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_BulkIn (void) { |
|||
|
|||
switch (BulkStage) { |
|||
case MSC_BS_DATA_IN: |
|||
switch (CBW.CB[0]) { |
|||
case SCSI_READ10: |
|||
MSC_MemoryRead(); |
|||
break; |
|||
} |
|||
break; |
|||
case MSC_BS_DATA_IN_LAST: |
|||
MSC_SetCSW(); |
|||
break; |
|||
case MSC_BS_DATA_IN_LAST_STALL: |
|||
USB_SetStallEP(MSC_EP_IN); |
|||
MSC_SetCSW(); |
|||
break; |
|||
case MSC_BS_CSW: |
|||
BulkStage = MSC_BS_CBW; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* MSC Bulk Out Callback |
|||
* Parameters: None (global variables) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void MSC_BulkOut (void) { |
|||
|
|||
BulkLen = (uint8_t)USB_ReadEP(MSC_EP_OUT, BulkBuf); |
|||
switch (BulkStage) { |
|||
case MSC_BS_CBW: |
|||
MSC_GetCBW(); |
|||
break; |
|||
case MSC_BS_DATA_OUT: |
|||
switch (CBW.CB[0]) { |
|||
case SCSI_WRITE10: |
|||
MSC_MemoryWrite(); |
|||
break; |
|||
case SCSI_VERIFY10: |
|||
MSC_MemoryVerify(); |
|||
break; |
|||
} |
|||
break; |
|||
default: |
|||
USB_SetStallEP(MSC_EP_OUT); |
|||
CSW.bStatus = CSW_PHASE_ERROR; |
|||
MSC_SetCSW(); |
|||
break; |
|||
} |
|||
} |
@ -0,0 +1,69 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: MSCUSER.H |
|||
* Purpose: Mass Storage Class Custom User Definitions |
|||
* Version: V1.10 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC family microcontroller devices only. Nothing |
|||
* else gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2005-2009 Keil Software. |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
#ifndef __MSCUSER_H__ |
|||
#define __MSCUSER_H__ |
|||
|
|||
|
|||
/* Max In/Out Packet Size */ |
|||
#define MSC_MAX_PACKET 64 |
|||
#define MSC_BLOCK_SIZE 512 |
|||
|
|||
/* MSC In/Out Endpoint Address */ |
|||
#define MSC_EP_IN 0x85 |
|||
#define MSC_EP_OUT 0x05 |
|||
|
|||
/* MSC Requests Callback Functions */ |
|||
extern uint32_t MSC_Reset (void); |
|||
extern uint32_t MSC_GetMaxLUN (void); |
|||
|
|||
/* MSC Bulk Callback Functions */ |
|||
extern void MSC_GetCBW (void); |
|||
extern void MSC_SetCSW (void); |
|||
extern void MSC_BulkIn (void); |
|||
extern void MSC_BulkOut(void); |
|||
|
|||
enum class Sense_KEY : uint8_t { |
|||
NO_SENSE, |
|||
RECOVERED_ERROR, |
|||
NOT_READY, |
|||
MEDIUM_ERROR, |
|||
HARDWARE_ERROR, |
|||
ILLEGAL_REQUEST, |
|||
UNIT_ATTENTION, |
|||
DATA_PROTECT |
|||
}; |
|||
|
|||
enum class Sense_ASC : uint8_t { |
|||
CANNOT_READ_MEDIUM = 0x30, |
|||
MEDIUM_NOT_PRESENT = 0x3A |
|||
}; |
|||
|
|||
enum class Sense_ASCQ : uint8_t { |
|||
// CANNOT_READ_MEDIUM
|
|||
UNKNOWN_FORMAT = 0x01, |
|||
// MEDIUM_NOT_PRESENT
|
|||
REASON_UNKNOWN = 0x00, |
|||
TRAY_CLOSED, |
|||
TRAY_OPEN, |
|||
LOADABLE, |
|||
AUXILIARY_MEMORY_ACCESSIBLE |
|||
}; |
|||
|
|||
|
|||
#endif /* __MSCUSER_H__ */ |
@ -0,0 +1,353 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: usb.h |
|||
* Purpose: USB Definitions |
|||
* Version: V1.20 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC family microcontroller devices only. Nothing |
|||
* else gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
#ifndef __USB_H__ |
|||
#define __USB_H__ |
|||
extern "C" { |
|||
#include "lpc_types.h" |
|||
} |
|||
#if defined ( __GNUC__ ) |
|||
#define __packed __attribute__((__packed__)) |
|||
#endif |
|||
|
|||
#if defined ( __CC_ARM ) |
|||
typedef __packed union { |
|||
#elif defined ( __GNUC__ ) |
|||
typedef union __packed { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
#pragma pack(1) |
|||
typedef union { |
|||
#endif |
|||
uint16_t W; |
|||
#if defined ( __CC_ARM ) |
|||
__packed struct { |
|||
#elif defined ( __GNUC__ ) |
|||
struct __packed { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
#pragma pack(1) |
|||
struct { |
|||
#endif |
|||
uint8_t L; |
|||
uint8_t H; |
|||
} WB; |
|||
#ifdef __IAR_SYSTEMS_ICC__ |
|||
#pragma pack() |
|||
#endif |
|||
} WORD_BYTE; |
|||
#ifdef __IAR_SYSTEMS_ICC__ |
|||
#pragma pack() |
|||
#endif |
|||
|
|||
|
|||
/* bmRequestType.Dir */ |
|||
#define REQUEST_HOST_TO_DEVICE 0 |
|||
#define REQUEST_DEVICE_TO_HOST 1 |
|||
|
|||
/* bmRequestType.Type */ |
|||
#define REQUEST_STANDARD 0 |
|||
#define REQUEST_CLASS 1 |
|||
#define REQUEST_VENDOR 2 |
|||
#define REQUEST_RESERVED 3 |
|||
|
|||
/* bmRequestType.Recipient */ |
|||
#define REQUEST_TO_DEVICE 0 |
|||
#define REQUEST_TO_INTERFACE 1 |
|||
#define REQUEST_TO_ENDPOINT 2 |
|||
#define REQUEST_TO_OTHER 3 |
|||
|
|||
/* bmRequestType Definition */ |
|||
#if defined ( __CC_ARM ) |
|||
typedef __packed union _REQUEST_TYPE { |
|||
#elif defined ( __GNUC__ ) |
|||
typedef union __packed _REQUEST_TYPE { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
#pragma pack(1) |
|||
typedef union _REQUEST_TYPE { |
|||
#endif |
|||
#if defined ( __CC_ARM ) |
|||
__packed struct _BM { |
|||
#elif defined ( __GNUC__ ) |
|||
struct __packed _BM { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
#pragma pack(1) |
|||
struct _BM { |
|||
#endif |
|||
uint8_t Recipient : 5; |
|||
uint8_t Type : 2; |
|||
uint8_t Dir : 1; |
|||
} BM; |
|||
#ifdef __IAR_SYSTEMS_ICC__ |
|||
#pragma pack() |
|||
#endif |
|||
uint8_t B; |
|||
} REQUEST_TYPE; |
|||
#ifdef __IAR_SYSTEMS_ICC__ |
|||
#pragma pack() |
|||
#endif |
|||
|
|||
/* USB Standard Request Codes */ |
|||
#define USB_REQUEST_GET_STATUS 0 |
|||
#define USB_REQUEST_CLEAR_FEATURE 1 |
|||
#define USB_REQUEST_SET_FEATURE 3 |
|||
#define USB_REQUEST_SET_ADDRESS 5 |
|||
#define USB_REQUEST_GET_DESCRIPTOR 6 |
|||
#define USB_REQUEST_SET_DESCRIPTOR 7 |
|||
#define USB_REQUEST_GET_CONFIGURATION 8 |
|||
#define USB_REQUEST_SET_CONFIGURATION 9 |
|||
#define USB_REQUEST_GET_INTERFACE 10 |
|||
#define USB_REQUEST_SET_INTERFACE 11 |
|||
#define USB_REQUEST_SYNC_FRAME 12 |
|||
|
|||
/* USB GET_STATUS Bit Values */ |
|||
#define USB_GETSTATUS_SELF_POWERED 0x01 |
|||
#define USB_GETSTATUS_REMOTE_WAKEUP 0x02 |
|||
#define USB_GETSTATUS_ENDPOINT_STALL 0x01 |
|||
|
|||
/* USB Standard Feature selectors */ |
|||
#define USB_FEATURE_ENDPOINT_STALL 0 |
|||
#define USB_FEATURE_REMOTE_WAKEUP 1 |
|||
|
|||
/* USB Default Control Pipe Setup Packet */ |
|||
#if defined ( __CC_ARM ) |
|||
typedef __packed struct _USB_SETUP_PACKET { |
|||
#elif defined ( __GNUC__ ) |
|||
typedef struct __packed _USB_SETUP_PACKET { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
#pragma pack(1) |
|||
typedef struct _USB_SETUP_PACKET { |
|||
#endif |
|||
REQUEST_TYPE bmRequestType; |
|||
uint8_t bRequest; |
|||
WORD_BYTE wValue; |
|||
WORD_BYTE wIndex; |
|||
uint16_t wLength; |
|||
} USB_SETUP_PACKET; |
|||
#ifdef __IAR_SYSTEMS_ICC__ |
|||
#pragma pack() |
|||
#endif |
|||
|
|||
|
|||
/* USB Descriptor Types */ |
|||
#define USB_DEVICE_DESCRIPTOR_TYPE 1 |
|||
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2 |
|||
#define USB_STRING_DESCRIPTOR_TYPE 3 |
|||
#define USB_INTERFACE_DESCRIPTOR_TYPE 4 |
|||
#define USB_ENDPOINT_DESCRIPTOR_TYPE 5 |
|||
#define USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE 6 |
|||
#define USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE 7 |
|||
#define USB_INTERFACE_POWER_DESCRIPTOR_TYPE 8 |
|||
#define USB_OTG_DESCRIPTOR_TYPE 9 |
|||
#define USB_DEBUG_DESCRIPTOR_TYPE 10 |
|||
#define USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE 11 |
|||
|
|||
/* USB Device Classes */ |
|||
#define USB_DEVICE_CLASS_RESERVED 0x00 |
|||
#define USB_DEVICE_CLASS_AUDIO 0x01 |
|||
#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02 |
|||
#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 |
|||
#define USB_DEVICE_CLASS_MONITOR 0x04 |
|||
#define USB_DEVICE_CLASS_PHYSICAL_INTERFACE 0x05 |
|||
#define USB_DEVICE_CLASS_POWER 0x06 |
|||
#define USB_DEVICE_CLASS_PRINTER 0x07 |
|||
#define USB_DEVICE_CLASS_STORAGE 0x08 |
|||
#define USB_DEVICE_CLASS_HUB 0x09 |
|||
#define USB_DEVICE_CLASS_MISCELLANEOUS 0xEF |
|||
#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF |
|||
|
|||
/* bmAttributes in Configuration Descriptor */ |
|||
#define USB_CONFIG_POWERED_MASK 0x40 |
|||
#define USB_CONFIG_BUS_POWERED 0x80 |
|||
#define USB_CONFIG_SELF_POWERED 0xC0 |
|||
#define USB_CONFIG_REMOTE_WAKEUP 0x20 |
|||
|
|||
/* bMaxPower in Configuration Descriptor */ |
|||
#define USB_CONFIG_POWER_MA(mA) ((mA)/2) |
|||
|
|||
/* bEndpointAddress in Endpoint Descriptor */ |
|||
#define USB_ENDPOINT_DIRECTION_MASK 0x80 |
|||
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00) |
|||
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80) |
|||
|
|||
/* bmAttributes in Endpoint Descriptor */ |
|||
#define USB_ENDPOINT_TYPE_MASK 0x03 |
|||
#define USB_ENDPOINT_TYPE_CONTROL 0x00 |
|||
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01 |
|||
#define USB_ENDPOINT_TYPE_BULK 0x02 |
|||
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03 |
|||
#define USB_ENDPOINT_SYNC_MASK 0x0C |
|||
#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION 0x00 |
|||
#define USB_ENDPOINT_SYNC_ASYNCHRONOUS 0x04 |
|||
#define USB_ENDPOINT_SYNC_ADAPTIVE 0x08 |
|||
#define USB_ENDPOINT_SYNC_SYNCHRONOUS 0x0C |
|||
#define USB_ENDPOINT_USAGE_MASK 0x30 |
|||
#define USB_ENDPOINT_USAGE_DATA 0x00 |
|||
#define USB_ENDPOINT_USAGE_FEEDBACK 0x10 |
|||
#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK 0x20 |
|||
#define USB_ENDPOINT_USAGE_RESERVED 0x30 |
|||
|
|||
/* USB Standard Device Descriptor */ |
|||
#if defined ( __CC_ARM ) |
|||
typedef __packed struct _USB_DEVICE_DESCRIPTOR { |
|||
#elif defined ( __GNUC__ ) |
|||
typedef struct __packed _USB_DEVICE_DESCRIPTOR { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
#pragma pack(1) |
|||
typedef struct _USB_DEVICE_DESCRIPTOR { |
|||
#endif |
|||
uint8_t bLength; |
|||
uint8_t bDescriptorType; |
|||
uint16_t bcdUSB; |
|||
uint8_t bDeviceClass; |
|||
uint8_t bDeviceSubClass; |
|||
uint8_t bDeviceProtocol; |
|||
uint8_t bMaxPacketSize0; |
|||
uint16_t idVendor; |
|||
uint16_t idProduct; |
|||
uint16_t bcdDevice; |
|||
uint8_t iManufacturer; |
|||
uint8_t iProduct; |
|||
uint8_t iSerialNumber; |
|||
uint8_t bNumConfigurations; |
|||
} USB_DEVICE_DESCRIPTOR; |
|||
#ifdef __IAR_SYSTEMS_ICC__ |
|||
#pragma pack() |
|||
#endif |
|||
|
|||
/* USB 2.0 Device Qualifier Descriptor */ |
|||
#if defined ( __CC_ARM ) |
|||
typedef __packed struct _USB_DEVICE_QUALIFIER_DESCRIPTOR { |
|||
#elif defined ( __GNUC__ ) |
|||
typedef struct __packed _USB_DEVICE_QUALIFIER_DESCRIPTOR { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
#pragma pack(1) |
|||
typedef struct _USB_DEVICE_QUALIFIER_DESCRIPTOR { |
|||
#endif |
|||
uint8_t bLength; |
|||
uint8_t bDescriptorType; |
|||
uint16_t bcdUSB; |
|||
uint8_t bDeviceClass; |
|||
uint8_t bDeviceSubClass; |
|||
uint8_t bDeviceProtocol; |
|||
uint8_t bMaxPacketSize0; |
|||
uint8_t bNumConfigurations; |
|||
uint8_t bReserved; |
|||
} USB_DEVICE_QUALIFIER_DESCRIPTOR; |
|||
#ifdef __IAR_SYSTEMS_ICC__ |
|||
#pragma pack() |
|||
#endif |
|||
|
|||
#if defined ( __CC_ARM ) |
|||
typedef __packed struct _USB_CONFIGURATION_DESCRIPTOR { |
|||
#elif defined ( __GNUC__ ) |
|||
typedef struct __packed _USB_CONFIGURATION_DESCRIPTOR { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
#pragma pack(1) |
|||
typedef struct _USB_CONFIGURATION_DESCRIPTOR { |
|||
#endif |
|||
uint8_t bLength; |
|||
uint8_t bDescriptorType; |
|||
uint16_t wTotalLength; |
|||
uint8_t bNumInterfaces; |
|||
uint8_t bConfigurationValue; |
|||
uint8_t iConfiguration; |
|||
uint8_t bmAttributes; |
|||
uint8_t bMaxPower; |
|||
} USB_CONFIGURATION_DESCRIPTOR; |
|||
#ifdef __IAR_SYSTEMS_ICC__ |
|||
#pragma pack() |
|||
#endif |
|||
|
|||
/* USB Standard Interface Descriptor */ |
|||
#if defined ( __CC_ARM ) |
|||
typedef __packed struct _USB_INTERFACE_DESCRIPTOR { |
|||
#elif defined ( __GNUC__ ) |
|||
typedef struct __packed _USB_INTERFACE_DESCRIPTOR { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
#pragma pack(1) |
|||
typedef struct _USB_INTERFACE_DESCRIPTOR { |
|||
#endif |
|||
uint8_t bLength; |
|||
uint8_t bDescriptorType; |
|||
uint8_t bInterfaceNumber; |
|||
uint8_t bAlternateSetting; |
|||
uint8_t bNumEndpoints; |
|||
uint8_t bInterfaceClass; |
|||
uint8_t bInterfaceSubClass; |
|||
uint8_t bInterfaceProtocol; |
|||
uint8_t iInterface; |
|||
} USB_INTERFACE_DESCRIPTOR; |
|||
#ifdef __IAR_SYSTEMS_ICC__ |
|||
#pragma pack() |
|||
#endif |
|||
|
|||
/* USB Standard Endpoint Descriptor */ |
|||
#if defined ( __CC_ARM ) |
|||
typedef __packed struct _USB_ENDPOINT_DESCRIPTOR { |
|||
#elif defined ( __GNUC__ ) |
|||
typedef struct __packed _USB_ENDPOINT_DESCRIPTOR { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
#pragma pack(1) |
|||
typedef struct _USB_ENDPOINT_DESCRIPTOR { |
|||
#endif |
|||
uint8_t bLength; |
|||
uint8_t bDescriptorType; |
|||
uint8_t bEndpointAddress; |
|||
uint8_t bmAttributes; |
|||
uint16_t wMaxPacketSize; |
|||
uint8_t bInterval; |
|||
} USB_ENDPOINT_DESCRIPTOR; |
|||
#ifdef __IAR_SYSTEMS_ICC__ |
|||
#pragma pack() |
|||
#endif |
|||
|
|||
/* USB String Descriptor */ |
|||
#if defined ( __CC_ARM ) |
|||
typedef __packed struct _USB_STRING_DESCRIPTOR { |
|||
#elif defined ( __GNUC__ ) |
|||
typedef struct __packed _USB_STRING_DESCRIPTOR { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
#pragma pack(1) |
|||
typedef struct _USB_STRING_DESCRIPTOR { |
|||
#endif |
|||
uint8_t bLength; |
|||
uint8_t bDescriptorType; |
|||
uint16_t bString/*[]*/; |
|||
} USB_STRING_DESCRIPTOR; |
|||
#ifdef __IAR_SYSTEMS_ICC__ |
|||
#pragma pack() |
|||
#endif |
|||
|
|||
/* USB Common Descriptor */ |
|||
#if defined ( __CC_ARM ) |
|||
typedef __packed struct _USB_COMMON_DESCRIPTOR { |
|||
#elif defined ( __GNUC__ ) |
|||
typedef struct __packed _USB_COMMON_DESCRIPTOR { |
|||
#elif defined ( __IAR_SYSTEMS_ICC__ ) |
|||
#pragma pack(1) |
|||
typedef struct _USB_COMMON_DESCRIPTOR { |
|||
#endif |
|||
uint8_t bLength; |
|||
uint8_t bDescriptorType; |
|||
} USB_COMMON_DESCRIPTOR; |
|||
#ifdef __IAR_SYSTEMS_ICC__ |
|||
#pragma pack() |
|||
#endif |
|||
|
|||
|
|||
|
|||
#endif /* __USB_H__ */ |
@ -0,0 +1,181 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: usbcfg.h |
|||
* Purpose: USB Custom Configuration |
|||
* Version: V1.20 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC family microcontroller devices only. Nothing |
|||
* else gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------- |
|||
* History: |
|||
* V1.20 Added vendor specific support |
|||
* V1.00 Initial Version |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
#ifndef __USBCFG_H__ |
|||
#define __USBCFG_H__ |
|||
|
|||
|
|||
//*** <<< Use Configuration Wizard in Context Menu >>> ***
|
|||
|
|||
|
|||
/*
|
|||
// <h> USB Configuration
|
|||
// <o0> USB Power
|
|||
// <i> Default Power Setting
|
|||
// <0=> Bus-powered
|
|||
// <1=> Self-powered
|
|||
// <o1> Max Number of Interfaces <1-256>
|
|||
// <o2> Max Number of Endpoints <1-32>
|
|||
// <o3> Max Endpoint 0 Packet Size
|
|||
// <8=> 8 Bytes <16=> 16 Bytes <32=> 32 Bytes <64=> 64 Bytes
|
|||
// <e4> DMA Transfer
|
|||
// <i> Use DMA for selected Endpoints
|
|||
// <o5.0> Endpoint 0 Out
|
|||
// <o5.1> Endpoint 0 In
|
|||
// <o5.2> Endpoint 1 Out
|
|||
// <o5.3> Endpoint 1 In
|
|||
// <o5.4> Endpoint 2 Out
|
|||
// <o5.5> Endpoint 2 In
|
|||
// <o5.6> Endpoint 3 Out
|
|||
// <o5.7> Endpoint 3 In
|
|||
// <o5.8> Endpoint 4 Out
|
|||
// <o5.9> Endpoint 4 In
|
|||
// <o5.10> Endpoint 5 Out
|
|||
// <o5.11> Endpoint 5 In
|
|||
// <o5.12> Endpoint 6 Out
|
|||
// <o5.13> Endpoint 6 In
|
|||
// <o5.14> Endpoint 7 Out
|
|||
// <o5.15> Endpoint 7 In
|
|||
// <o5.16> Endpoint 8 Out
|
|||
// <o5.17> Endpoint 8 In
|
|||
// <o5.18> Endpoint 9 Out
|
|||
// <o5.19> Endpoint 9 In
|
|||
// <o5.20> Endpoint 10 Out
|
|||
// <o5.21> Endpoint 10 In
|
|||
// <o5.22> Endpoint 11 Out
|
|||
// <o5.23> Endpoint 11 In
|
|||
// <o5.24> Endpoint 12 Out
|
|||
// <o5.25> Endpoint 12 In
|
|||
// <o5.26> Endpoint 13 Out
|
|||
// <o5.27> Endpoint 13 In
|
|||
// <o5.28> Endpoint 14 Out
|
|||
// <o5.29> Endpoint 14 In
|
|||
// <o5.30> Endpoint 15 Out
|
|||
// <o5.31> Endpoint 15 In
|
|||
// </e>
|
|||
// </h>
|
|||
*/ |
|||
|
|||
#define USB_POWER 0 |
|||
#define USB_IF_NUM 4 |
|||
#define USB_EP_NUM 32 |
|||
#define USB_MAX_PACKET0 64 |
|||
#define USB_DMA 0 |
|||
#define USB_DMA_EP 0x00000000 |
|||
|
|||
|
|||
/*
|
|||
// <h> USB Event Handlers
|
|||
// <h> Device Events
|
|||
// <o0.0> Power Event
|
|||
// <o1.0> Reset Event
|
|||
// <o2.0> Suspend Event
|
|||
// <o3.0> Resume Event
|
|||
// <o4.0> Remote Wakeup Event
|
|||
// <o5.0> Start of Frame Event
|
|||
// <o6.0> Error Event
|
|||
// </h>
|
|||
// <h> Endpoint Events
|
|||
// <o7.0> Endpoint 0 Event
|
|||
// <o7.1> Endpoint 1 Event
|
|||
// <o7.2> Endpoint 2 Event
|
|||
// <o7.3> Endpoint 3 Event
|
|||
// <o7.4> Endpoint 4 Event
|
|||
// <o7.5> Endpoint 5 Event
|
|||
// <o7.6> Endpoint 6 Event
|
|||
// <o7.7> Endpoint 7 Event
|
|||
// <o7.8> Endpoint 8 Event
|
|||
// <o7.9> Endpoint 9 Event
|
|||
// <o7.10> Endpoint 10 Event
|
|||
// <o7.11> Endpoint 11 Event
|
|||
// <o7.12> Endpoint 12 Event
|
|||
// <o7.13> Endpoint 13 Event
|
|||
// <o7.14> Endpoint 14 Event
|
|||
// <o7.15> Endpoint 15 Event
|
|||
// </h>
|
|||
// <h> USB Core Events
|
|||
// <o8.0> Set Configuration Event
|
|||
// <o9.0> Set Interface Event
|
|||
// <o10.0> Set/Clear Feature Event
|
|||
// </h>
|
|||
// </h>
|
|||
*/ |
|||
|
|||
#define USB_POWER_EVENT 0 |
|||
#define USB_RESET_EVENT 1 |
|||
#define USB_SUSPEND_EVENT 0 |
|||
#define USB_RESUME_EVENT 0 |
|||
#define USB_WAKEUP_EVENT 0 |
|||
#define USB_SOF_EVENT 0 |
|||
#define USB_ERROR_EVENT 0 |
|||
#define USB_EP_EVENT 0x0027 |
|||
#define USB_CONFIGURE_EVENT 1 |
|||
#define USB_INTERFACE_EVENT 0 |
|||
#define USB_FEATURE_EVENT 0 |
|||
|
|||
|
|||
/*
|
|||
// <e0> USB Class Support
|
|||
// <i> enables USB Class specific Requests
|
|||
// <e1> Human Interface Device (HID)
|
|||
// <o2> Interface Number <0-255>
|
|||
// </e>
|
|||
// <e3> Mass Storage
|
|||
// <o4> Interface Number <0-255>
|
|||
// </e>
|
|||
// <e5> Audio Device
|
|||
// <o6> Control Interface Number <0-255>
|
|||
// <o7> Streaming Interface 1 Number <0-255>
|
|||
// <o8> Streaming Interface 2 Number <0-255>
|
|||
// </e>
|
|||
// <e9> Communication Device
|
|||
// <o10> Control Interface Number <0-255>
|
|||
// <o11> Bulk Interface Number <0-255>
|
|||
// <o12> Max Communication Device Buffer Size
|
|||
// <8=> 8 Bytes <16=> 16 Bytes <32=> 32 Bytes <64=> 64 Bytes
|
|||
// </e>
|
|||
// </e>
|
|||
*/ |
|||
|
|||
#define USB_CLASS 1 |
|||
#define USB_HID 0 |
|||
#define USB_HID_IF_NUM 0 |
|||
#define USB_MSC 1 |
|||
#define USB_MSC_IF_NUM 2 |
|||
#define USB_AUDIO 0 |
|||
#define USB_ADC_CIF_NUM 0 |
|||
#define USB_ADC_SIF1_NUM 1 |
|||
#define USB_ADC_SIF2_NUM 2 |
|||
#define USB_CDC 1 |
|||
#define USB_CDC_CIF_NUM 0 |
|||
#define USB_CDC_DIF_NUM 1 |
|||
#define USB_CDC_BUFSIZE 64 |
|||
|
|||
/*
|
|||
// <e0> USB Vendor Support
|
|||
// <i> enables USB Vendor specific Requests
|
|||
// </e>
|
|||
*/ |
|||
#define USB_VENDOR 0 |
|||
|
|||
|
|||
#endif /* __USBCFG_H__ */ |
@ -0,0 +1,815 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: usbcore.c |
|||
* Purpose: USB Core Module |
|||
* Version: V1.20 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC family microcontroller devices only. Nothing |
|||
* else gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------- |
|||
* History: |
|||
* V1.20 Added vendor specific requests |
|||
* Changed string descriptor handling |
|||
* Reworked Endpoint0 |
|||
* V1.00 Initial Version |
|||
*----------------------------------------------------------------------------*/ |
|||
extern "C" { |
|||
#include "lpc_types.h" |
|||
} |
|||
#include "usb.h" |
|||
#include "usbcfg.h" |
|||
#include "usbhw.h" |
|||
#include "usbcore.h" |
|||
#include "usbdesc.h" |
|||
#include "usbuser.h" |
|||
|
|||
#include "msc.h" |
|||
#include "mscuser.h" |
|||
extern MSC_CSW CSW; |
|||
|
|||
#include "cdc.h" |
|||
#include "cdcuser.h" |
|||
|
|||
#define __packed __attribute__((__packed__)) |
|||
|
|||
uint16_t USB_DeviceStatus; |
|||
uint8_t USB_DeviceAddress; |
|||
uint8_t USB_Configuration; |
|||
uint32_t USB_EndPointMask; |
|||
uint32_t USB_EndPointHalt; |
|||
uint32_t USB_EndPointStall; /* EP must stay stalled */ |
|||
uint8_t USB_NumInterfaces; |
|||
uint8_t USB_AltSetting[USB_IF_NUM]; |
|||
|
|||
uint8_t EP0Buf[USB_MAX_PACKET0]; |
|||
|
|||
USB_EP_DATA EP0Data; |
|||
|
|||
USB_SETUP_PACKET SetupPacket; |
|||
|
|||
/*
|
|||
* Reset USB Core |
|||
* Parameters: None |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_ResetCore(void) { |
|||
|
|||
USB_DeviceStatus = USB_POWER; |
|||
USB_DeviceAddress = 0; |
|||
USB_Configuration = 0; |
|||
USB_EndPointMask = 0x00010001; |
|||
USB_EndPointHalt = 0x00000000; |
|||
USB_EndPointStall = 0x00000000; |
|||
} |
|||
|
|||
/*
|
|||
* USB Request - Setup Stage |
|||
* Parameters: None (global SetupPacket) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_SetupStage(void) { |
|||
USB_ReadEP(0x00, (uint8_t *) &SetupPacket); |
|||
} |
|||
|
|||
/*
|
|||
* USB Request - Data In Stage |
|||
* Parameters: None (global EP0Data) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_DataInStage(void) { |
|||
uint32_t cnt; |
|||
|
|||
if (EP0Data.Count > USB_MAX_PACKET0) { |
|||
cnt = USB_MAX_PACKET0; |
|||
} else { |
|||
cnt = EP0Data.Count; |
|||
} |
|||
cnt = USB_WriteEP(0x80, EP0Data.pData, cnt); |
|||
EP0Data.pData += cnt; |
|||
EP0Data.Count -= cnt; |
|||
} |
|||
|
|||
/*
|
|||
* USB Request - Data Out Stage |
|||
* Parameters: None (global EP0Data) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_DataOutStage(void) { |
|||
uint32_t cnt; |
|||
|
|||
cnt = USB_ReadEP(0x00, EP0Data.pData); |
|||
EP0Data.pData += cnt; |
|||
EP0Data.Count -= cnt; |
|||
} |
|||
|
|||
/*
|
|||
* USB Request - Status In Stage |
|||
* Parameters: None |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_StatusInStage(void) { |
|||
USB_WriteEP(0x80, nullptr, 0); |
|||
} |
|||
|
|||
/*
|
|||
* USB Request - Status Out Stage |
|||
* Parameters: None |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_StatusOutStage(void) { |
|||
USB_ReadEP(0x00, EP0Buf); |
|||
} |
|||
|
|||
/*
|
|||
* Get Status USB Request |
|||
* Parameters: None (global SetupPacket) |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
|
|||
__inline uint32_t USB_ReqGetStatus(void) { |
|||
uint32_t n, m; |
|||
|
|||
switch (SetupPacket.bmRequestType.BM.Recipient) { |
|||
case REQUEST_TO_DEVICE: |
|||
EP0Data.pData = (uint8_t *) &USB_DeviceStatus; |
|||
break; |
|||
case REQUEST_TO_INTERFACE: |
|||
if ((USB_Configuration != 0) && (SetupPacket.wIndex.WB.L < USB_NumInterfaces)) { |
|||
*((__packed uint16_t *) EP0Buf) = 0; |
|||
*((uint16_t *) EP0Buf) = 0; |
|||
EP0Data.pData = EP0Buf; |
|||
} else { |
|||
return (FALSE); |
|||
} |
|||
break; |
|||
case REQUEST_TO_ENDPOINT: |
|||
n = SetupPacket.wIndex.WB.L & 0x8F; |
|||
m = (n & 0x80) ? ((1 << 16) << (n & 0x0F)) : (1 << n); |
|||
if (((USB_Configuration != 0) || ((n & 0x0F) == 0)) && (USB_EndPointMask & m)) { |
|||
*((__packed uint16_t *) EP0Buf) = (USB_EndPointHalt & m) ? 1 : 0; |
|||
*((uint16_t *) EP0Buf) = (USB_EndPointHalt & m) ? 1 : 0; |
|||
EP0Data.pData = EP0Buf; |
|||
} else { |
|||
return (FALSE); |
|||
} |
|||
break; |
|||
default: |
|||
return (FALSE); |
|||
} |
|||
return (TRUE); |
|||
} |
|||
|
|||
/*
|
|||
* Set/Clear Feature USB Request |
|||
* Parameters: sc: 0 - Clear, 1 - Set |
|||
* (global SetupPacket) |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
|
|||
__inline uint32_t USB_ReqSetClrFeature(uint32_t sc) { |
|||
uint32_t n, m; |
|||
|
|||
switch (SetupPacket.bmRequestType.BM.Recipient) { |
|||
case REQUEST_TO_DEVICE: |
|||
if (SetupPacket.wValue.W == USB_FEATURE_REMOTE_WAKEUP) { |
|||
if (sc) { |
|||
USB_WakeUpCfg(TRUE); |
|||
USB_DeviceStatus |= USB_GETSTATUS_REMOTE_WAKEUP; |
|||
} else { |
|||
USB_WakeUpCfg(FALSE); |
|||
USB_DeviceStatus &= ~USB_GETSTATUS_REMOTE_WAKEUP; |
|||
} |
|||
} else { |
|||
return (FALSE); |
|||
} |
|||
break; |
|||
case REQUEST_TO_INTERFACE: |
|||
return (FALSE); |
|||
case REQUEST_TO_ENDPOINT: |
|||
n = SetupPacket.wIndex.WB.L & 0x8F; |
|||
m = (n & 0x80) ? ((1 << 16) << (n & 0x0F)) : (1 << n); |
|||
if ((USB_Configuration != 0) && ((n & 0x0F) != 0) && (USB_EndPointMask & m)) { |
|||
if (SetupPacket.wValue.W == USB_FEATURE_ENDPOINT_STALL) { |
|||
if (sc) { |
|||
USB_SetStallEP(n); |
|||
USB_EndPointHalt |= m; |
|||
} else { |
|||
if ((USB_EndPointStall & m) != 0) { |
|||
return (TRUE); |
|||
} |
|||
USB_ClrStallEP(n); |
|||
#if (USB_MSC) |
|||
if ((n == MSC_EP_IN) && ((USB_EndPointHalt & m) != 0)) { |
|||
/* Compliance Test: rewrite CSW after unstall */ |
|||
if (CSW.dSignature == MSC_CSW_Signature) { |
|||
USB_WriteEP(MSC_EP_IN, (uint8_t *) &CSW, sizeof(CSW)); |
|||
} |
|||
} |
|||
#endif |
|||
USB_EndPointHalt &= ~m; |
|||
} |
|||
} else { |
|||
return (FALSE); |
|||
} |
|||
} else { |
|||
return (FALSE); |
|||
} |
|||
break; |
|||
default: |
|||
return (FALSE); |
|||
} |
|||
return (TRUE); |
|||
} |
|||
|
|||
/*
|
|||
* Set Address USB Request |
|||
* Parameters: None (global SetupPacket) |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
|
|||
__inline uint32_t USB_ReqSetAddress(void) { |
|||
switch (SetupPacket.bmRequestType.BM.Recipient) { |
|||
case REQUEST_TO_DEVICE: |
|||
USB_DeviceAddress = 0x80 | SetupPacket.wValue.WB.L; |
|||
break; |
|||
default: |
|||
return (FALSE); |
|||
} |
|||
return (TRUE); |
|||
} |
|||
|
|||
/*
|
|||
* Get Descriptor USB Request |
|||
* Parameters: None (global SetupPacket) |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
|
|||
__inline uint32_t USB_ReqGetDescriptor(void) { |
|||
uint8_t *pD; |
|||
uint32_t len, n; |
|||
|
|||
switch (SetupPacket.bmRequestType.BM.Recipient) { |
|||
case REQUEST_TO_DEVICE: |
|||
switch (SetupPacket.wValue.WB.H) { |
|||
case USB_DEVICE_DESCRIPTOR_TYPE: |
|||
EP0Data.pData = (uint8_t *) USB_DeviceDescriptor; |
|||
len = USB_DEVICE_DESC_SIZE; |
|||
break; |
|||
case USB_CONFIGURATION_DESCRIPTOR_TYPE: |
|||
pD = (uint8_t *) USB_ConfigDescriptor; |
|||
for (n = 0; n != SetupPacket.wValue.WB.L; n++) { |
|||
if (((USB_CONFIGURATION_DESCRIPTOR *) pD)->bLength != 0) { |
|||
pD += ((USB_CONFIGURATION_DESCRIPTOR *) pD)->wTotalLength; |
|||
} |
|||
} |
|||
if (((USB_CONFIGURATION_DESCRIPTOR *) pD)->bLength == 0) { |
|||
return (FALSE); |
|||
} |
|||
EP0Data.pData = pD; |
|||
len = ((USB_CONFIGURATION_DESCRIPTOR *) pD)->wTotalLength; |
|||
break; |
|||
case USB_STRING_DESCRIPTOR_TYPE: |
|||
pD = (uint8_t *) USB_StringDescriptor; |
|||
for (n = 0; n != SetupPacket.wValue.WB.L; n++) { |
|||
if (((USB_STRING_DESCRIPTOR *) pD)->bLength != 0) { |
|||
pD += ((USB_STRING_DESCRIPTOR *) pD)->bLength; |
|||
} |
|||
} |
|||
if (((USB_STRING_DESCRIPTOR *) pD)->bLength == 0) { |
|||
return (FALSE); |
|||
} |
|||
EP0Data.pData = pD; |
|||
len = ((USB_STRING_DESCRIPTOR *) EP0Data.pData)->bLength; |
|||
break; |
|||
default: |
|||
return (FALSE); |
|||
} |
|||
break; |
|||
case REQUEST_TO_INTERFACE: |
|||
switch (SetupPacket.wValue.WB.H) { |
|||
default: |
|||
return (FALSE); |
|||
} |
|||
// break;
|
|||
default: |
|||
return (FALSE); |
|||
} |
|||
|
|||
if (EP0Data.Count > len) { |
|||
EP0Data.Count = len; |
|||
} |
|||
|
|||
return (TRUE); |
|||
} |
|||
|
|||
/*
|
|||
* Get Configuration USB Request |
|||
* Parameters: None (global SetupPacket) |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
|
|||
__inline uint32_t USB_ReqGetConfiguration(void) { |
|||
switch (SetupPacket.bmRequestType.BM.Recipient) { |
|||
case REQUEST_TO_DEVICE: |
|||
EP0Data.pData = &USB_Configuration; |
|||
break; |
|||
default: |
|||
return (FALSE); |
|||
} |
|||
return (TRUE); |
|||
} |
|||
|
|||
/*
|
|||
* Set Configuration USB Request |
|||
* Parameters: None (global SetupPacket) |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
|
|||
__inline uint32_t USB_ReqSetConfiguration(void) { |
|||
USB_COMMON_DESCRIPTOR *pD; |
|||
uint32_t alt = 0; |
|||
uint32_t n, m; |
|||
uint32_t tmp; |
|||
|
|||
switch (SetupPacket.bmRequestType.BM.Recipient) { |
|||
case REQUEST_TO_DEVICE: |
|||
|
|||
if (SetupPacket.wValue.WB.L) { |
|||
pD = (USB_COMMON_DESCRIPTOR *) USB_ConfigDescriptor; |
|||
while (pD->bLength) { |
|||
switch (pD->bDescriptorType) { |
|||
case USB_CONFIGURATION_DESCRIPTOR_TYPE: |
|||
if (((USB_CONFIGURATION_DESCRIPTOR *) pD)->bConfigurationValue == SetupPacket.wValue.WB.L) { |
|||
USB_Configuration = SetupPacket.wValue.WB.L; |
|||
USB_NumInterfaces = ((USB_CONFIGURATION_DESCRIPTOR *) pD)->bNumInterfaces; |
|||
for (n = 0; n < USB_IF_NUM; n++) { |
|||
USB_AltSetting[n] = 0; |
|||
} |
|||
for (n = 1; n < 16; n++) { |
|||
if (USB_EndPointMask & (1 << n)) { |
|||
USB_DisableEP(n); |
|||
} |
|||
if (USB_EndPointMask & ((1 << 16) << n)) { |
|||
USB_DisableEP(n | 0x80); |
|||
} |
|||
} |
|||
USB_EndPointMask = 0x00010001; |
|||
USB_EndPointHalt = 0x00000000; |
|||
USB_EndPointStall = 0x00000000; |
|||
USB_Configure(TRUE); |
|||
if (((USB_CONFIGURATION_DESCRIPTOR *) pD)->bmAttributes & USB_CONFIG_POWERED_MASK) { |
|||
USB_DeviceStatus |= USB_GETSTATUS_SELF_POWERED; |
|||
} else { |
|||
USB_DeviceStatus &= ~(USB_GETSTATUS_SELF_POWERED); |
|||
} |
|||
} else { |
|||
// (uint8_t *)pD += ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength;
|
|||
tmp = (uint32_t) pD; |
|||
tmp += ((USB_CONFIGURATION_DESCRIPTOR *) pD)->wTotalLength; |
|||
pD = (USB_COMMON_DESCRIPTOR *) tmp; |
|||
continue; |
|||
} |
|||
break; |
|||
case USB_INTERFACE_DESCRIPTOR_TYPE: |
|||
alt = ((USB_INTERFACE_DESCRIPTOR *) pD)->bAlternateSetting; |
|||
break; |
|||
case USB_ENDPOINT_DESCRIPTOR_TYPE: |
|||
if (alt == 0) { |
|||
n = ((USB_ENDPOINT_DESCRIPTOR *) pD)->bEndpointAddress & 0x8F; |
|||
m = (n & 0x80) ? ((1 << 16) << (n & 0x0F)) : (1 << n); |
|||
USB_EndPointMask |= m; |
|||
USB_ConfigEP((USB_ENDPOINT_DESCRIPTOR *) pD); |
|||
USB_EnableEP(n); |
|||
USB_ResetEP(n); |
|||
} |
|||
break; |
|||
} |
|||
// (uint8_t *)pD += pD->bLength;
|
|||
tmp = (uint32_t) pD; |
|||
tmp += pD->bLength; |
|||
pD = (USB_COMMON_DESCRIPTOR *) tmp; |
|||
} |
|||
} else { |
|||
USB_Configuration = 0; |
|||
for (n = 1; n < 16; n++) { |
|||
if (USB_EndPointMask & (1 << n)) { |
|||
USB_DisableEP(n); |
|||
} |
|||
if (USB_EndPointMask & ((1 << 16) << n)) { |
|||
USB_DisableEP(n | 0x80); |
|||
} |
|||
} |
|||
USB_EndPointMask = 0x00010001; |
|||
USB_EndPointHalt = 0x00000000; |
|||
USB_EndPointStall = 0x00000000; |
|||
USB_Configure(FALSE); |
|||
} |
|||
|
|||
if (USB_Configuration != SetupPacket.wValue.WB.L) { |
|||
return (FALSE); |
|||
} |
|||
break; |
|||
default: |
|||
return (FALSE); |
|||
} |
|||
return (TRUE); |
|||
} |
|||
|
|||
/*
|
|||
* Get Interface USB Request |
|||
* Parameters: None (global SetupPacket) |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
|
|||
__inline uint32_t USB_ReqGetInterface(void) { |
|||
switch (SetupPacket.bmRequestType.BM.Recipient) { |
|||
case REQUEST_TO_INTERFACE: |
|||
if ((USB_Configuration != 0) && (SetupPacket.wIndex.WB.L < USB_NumInterfaces)) { |
|||
EP0Data.pData = USB_AltSetting + SetupPacket.wIndex.WB.L; |
|||
} else { |
|||
return (FALSE); |
|||
} |
|||
break; |
|||
default: |
|||
return (FALSE); |
|||
} |
|||
return (TRUE); |
|||
} |
|||
|
|||
/*
|
|||
* Set Interface USB Request |
|||
* Parameters: None (global SetupPacket) |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
__inline uint32_t USB_ReqSetInterface(void) { |
|||
USB_COMMON_DESCRIPTOR *pD; |
|||
uint32_t ifn = 0, alt = 0, old = 0, msk = 0; |
|||
uint32_t n, m; |
|||
uint32_t set; |
|||
uint32_t tmp; |
|||
|
|||
switch (SetupPacket.bmRequestType.BM.Recipient) { |
|||
case REQUEST_TO_INTERFACE: |
|||
if (USB_Configuration == 0) |
|||
return (FALSE); |
|||
set = FALSE; |
|||
pD = (USB_COMMON_DESCRIPTOR *) USB_ConfigDescriptor; |
|||
while (pD->bLength) { |
|||
switch (pD->bDescriptorType) { |
|||
case USB_CONFIGURATION_DESCRIPTOR_TYPE: |
|||
if (((USB_CONFIGURATION_DESCRIPTOR *) pD)->bConfigurationValue != USB_Configuration) { |
|||
// (uint8_t *)pD += ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength;
|
|||
tmp = (uint32_t) pD; |
|||
tmp += ((USB_CONFIGURATION_DESCRIPTOR *) pD)->wTotalLength; |
|||
pD = (USB_COMMON_DESCRIPTOR *) tmp; |
|||
|
|||
continue; |
|||
} |
|||
break; |
|||
case USB_INTERFACE_DESCRIPTOR_TYPE: |
|||
ifn = ((USB_INTERFACE_DESCRIPTOR *) pD)->bInterfaceNumber; |
|||
alt = ((USB_INTERFACE_DESCRIPTOR *) pD)->bAlternateSetting; |
|||
msk = 0; |
|||
if ((ifn == SetupPacket.wIndex.WB.L) && (alt == SetupPacket.wValue.WB.L)) { |
|||
set = TRUE; |
|||
old = USB_AltSetting[ifn]; |
|||
USB_AltSetting[ifn] = (uint8_t) alt; |
|||
} |
|||
break; |
|||
case USB_ENDPOINT_DESCRIPTOR_TYPE: |
|||
if (ifn == SetupPacket.wIndex.WB.L) { |
|||
n = ((USB_ENDPOINT_DESCRIPTOR *) pD)->bEndpointAddress & 0x8F; |
|||
m = (n & 0x80) ? ((1 << 16) << (n & 0x0F)) : (1 << n); |
|||
if (alt == SetupPacket.wValue.WB.L) { |
|||
USB_EndPointMask |= m; |
|||
USB_EndPointHalt &= ~m; |
|||
USB_ConfigEP((USB_ENDPOINT_DESCRIPTOR *) pD); |
|||
USB_EnableEP(n); |
|||
USB_ResetEP(n); |
|||
msk |= m; |
|||
} else if ((alt == old) && ((msk & m) == 0)) { |
|||
USB_EndPointMask &= ~m; |
|||
USB_EndPointHalt &= ~m; |
|||
USB_DisableEP(n); |
|||
} |
|||
} |
|||
break; |
|||
} |
|||
// (uint8_t *)pD += pD->bLength;
|
|||
tmp = (uint32_t) pD; |
|||
tmp += pD->bLength; |
|||
pD = (USB_COMMON_DESCRIPTOR *) tmp; |
|||
} |
|||
break; |
|||
default: |
|||
return (FALSE); |
|||
} |
|||
|
|||
return (set); |
|||
} |
|||
|
|||
/*
|
|||
* USB Endpoint 0 Event Callback |
|||
* Parameters: event |
|||
* Return Value: none |
|||
*/ |
|||
|
|||
void USB_EndPoint0(uint32_t event) { |
|||
|
|||
switch (event) { |
|||
case USB_EVT_SETUP: |
|||
USB_SetupStage(); |
|||
USB_DirCtrlEP(SetupPacket.bmRequestType.BM.Dir); |
|||
EP0Data.Count = SetupPacket.wLength; /* Number of bytes to transfer */ |
|||
switch (SetupPacket.bmRequestType.BM.Type) { |
|||
|
|||
case REQUEST_STANDARD: |
|||
switch (SetupPacket.bRequest) { |
|||
case USB_REQUEST_GET_STATUS: |
|||
if (!USB_ReqGetStatus()) { |
|||
goto stall_i; |
|||
} |
|||
USB_DataInStage(); |
|||
break; |
|||
|
|||
case USB_REQUEST_CLEAR_FEATURE: |
|||
if (!USB_ReqSetClrFeature(0)) { |
|||
goto stall_i; |
|||
} |
|||
USB_StatusInStage(); |
|||
#if USB_FEATURE_EVENT |
|||
USB_Feature_Event(); |
|||
#endif |
|||
break; |
|||
|
|||
case USB_REQUEST_SET_FEATURE: |
|||
if (!USB_ReqSetClrFeature(1)) { |
|||
goto stall_i; |
|||
} |
|||
USB_StatusInStage(); |
|||
#if USB_FEATURE_EVENT |
|||
USB_Feature_Event(); |
|||
#endif |
|||
break; |
|||
|
|||
case USB_REQUEST_SET_ADDRESS: |
|||
if (!USB_ReqSetAddress()) { |
|||
goto stall_i; |
|||
} |
|||
USB_StatusInStage(); |
|||
break; |
|||
|
|||
case USB_REQUEST_GET_DESCRIPTOR: |
|||
if (!USB_ReqGetDescriptor()) { |
|||
goto stall_i; |
|||
} |
|||
USB_DataInStage(); |
|||
break; |
|||
|
|||
case USB_REQUEST_SET_DESCRIPTOR: |
|||
USB_SetStallEP(0x00); |
|||
EP0Data.Count = 0; |
|||
break; |
|||
|
|||
case USB_REQUEST_GET_CONFIGURATION: |
|||
if (!USB_ReqGetConfiguration()) { |
|||
goto stall_i; |
|||
} |
|||
USB_DataInStage(); |
|||
break; |
|||
|
|||
case USB_REQUEST_SET_CONFIGURATION: |
|||
if (!USB_ReqSetConfiguration()) { |
|||
goto stall_i; |
|||
} |
|||
USB_StatusInStage(); |
|||
#if USB_CONFIGURE_EVENT |
|||
USB_Configure_Event(); |
|||
#endif |
|||
break; |
|||
|
|||
case USB_REQUEST_GET_INTERFACE: |
|||
if (!USB_ReqGetInterface()) { |
|||
goto stall_i; |
|||
} |
|||
USB_DataInStage(); |
|||
break; |
|||
|
|||
case USB_REQUEST_SET_INTERFACE: |
|||
if (!USB_ReqSetInterface()) { |
|||
goto stall_i; |
|||
} |
|||
USB_StatusInStage(); |
|||
#if USB_INTERFACE_EVENT |
|||
USB_Interface_Event(); |
|||
#endif |
|||
break; |
|||
|
|||
default: |
|||
goto stall_i; |
|||
} |
|||
break; /* end case REQUEST_STANDARD */ |
|||
|
|||
case REQUEST_CLASS: |
|||
switch (SetupPacket.bmRequestType.BM.Recipient) { |
|||
|
|||
case REQUEST_TO_DEVICE: |
|||
goto stall_i; |
|||
/* not supported */ |
|||
|
|||
case REQUEST_TO_INTERFACE: |
|||
if (SetupPacket.wIndex.WB.L == USB_MSC_IF_NUM) { /* IF number correct? */ |
|||
switch (SetupPacket.bRequest) { |
|||
case MSC_REQUEST_RESET: |
|||
if ((SetupPacket.wValue.W == 0) && /* RESET with invalid parameters -> STALL */ |
|||
(SetupPacket.wLength == 0)) { |
|||
if (MSC_Reset()) { |
|||
USB_StatusInStage(); |
|||
goto setup_class_ok; |
|||
} |
|||
} |
|||
break; |
|||
case MSC_REQUEST_GET_MAX_LUN: |
|||
if ((SetupPacket.wValue.W == 0) && /* GET_MAX_LUN with invalid parameters -> STALL */ |
|||
(SetupPacket.wLength == 1)) { |
|||
if (MSC_GetMaxLUN()) { |
|||
EP0Data.pData = EP0Buf; |
|||
USB_DataInStage(); |
|||
goto setup_class_ok; |
|||
} |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
if ((SetupPacket.wIndex.WB.L == USB_CDC_CIF_NUM) || /* IF number correct? */ |
|||
(SetupPacket.wIndex.WB.L == USB_CDC_DIF_NUM)) { |
|||
switch (SetupPacket.bRequest) { |
|||
case CDC_SEND_ENCAPSULATED_COMMAND: |
|||
EP0Data.pData = EP0Buf; /* data to be received, see USB_EVT_OUT */ |
|||
goto setup_class_ok; |
|||
case CDC_GET_ENCAPSULATED_RESPONSE: |
|||
if (CDC_GetEncapsulatedResponse()) { |
|||
EP0Data.pData = EP0Buf; /* point to data to be sent */ |
|||
USB_DataInStage(); /* send requested data */ |
|||
goto setup_class_ok; |
|||
} |
|||
break; |
|||
case CDC_SET_COMM_FEATURE: |
|||
EP0Data.pData = EP0Buf; /* data to be received, see USB_EVT_OUT */ |
|||
goto setup_class_ok; |
|||
case CDC_GET_COMM_FEATURE: |
|||
if (CDC_GetCommFeature(SetupPacket.wValue.W)) { |
|||
EP0Data.pData = EP0Buf; /* point to data to be sent */ |
|||
USB_DataInStage(); /* send requested data */ |
|||
goto setup_class_ok; |
|||
} |
|||
break; |
|||
case CDC_CLEAR_COMM_FEATURE: |
|||
if (CDC_ClearCommFeature(SetupPacket.wValue.W)) { |
|||
USB_StatusInStage(); /* send Acknowledge */ |
|||
goto setup_class_ok; |
|||
} |
|||
break; |
|||
case CDC_SET_LINE_CODING: |
|||
EP0Data.pData = EP0Buf; /* data to be received, see USB_EVT_OUT */ |
|||
goto setup_class_ok; |
|||
case CDC_GET_LINE_CODING: |
|||
if (CDC_GetLineCoding()) { |
|||
EP0Data.pData = EP0Buf; /* point to data to be sent */ |
|||
USB_DataInStage(); /* send requested data */ |
|||
goto setup_class_ok; |
|||
} |
|||
break; |
|||
case CDC_SET_CONTROL_LINE_STATE: |
|||
if (CDC_SetControlLineState(SetupPacket.wValue.W)) { |
|||
USB_StatusInStage(); /* send Acknowledge */ |
|||
goto setup_class_ok; |
|||
} |
|||
break; |
|||
case CDC_SEND_BREAK: |
|||
if (CDC_SendBreak(SetupPacket.wValue.W)) { |
|||
USB_StatusInStage(); /* send Acknowledge */ |
|||
goto setup_class_ok; |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
goto stall_i; |
|||
/* not supported */ |
|||
/* end case REQUEST_TO_INTERFACE */ |
|||
|
|||
case REQUEST_TO_ENDPOINT: |
|||
goto stall_i; |
|||
/* end case REQUEST_TO_ENDPOINT */ |
|||
|
|||
default: |
|||
goto stall_i; |
|||
} |
|||
setup_class_ok: /* request finished successfully */ |
|||
break; /* end case REQUEST_CLASS */ |
|||
|
|||
default: |
|||
stall_i: USB_SetStallEP(0x80); |
|||
EP0Data.Count = 0; |
|||
break; |
|||
} |
|||
break; /* end case USB_EVT_SETUP */ |
|||
|
|||
case USB_EVT_OUT: |
|||
if (SetupPacket.bmRequestType.BM.Dir == REQUEST_HOST_TO_DEVICE) { |
|||
if (EP0Data.Count) { /* still data to receive ? */ |
|||
USB_DataOutStage(); /* receive data */ |
|||
if (EP0Data.Count == 0) { /* data complete ? */ |
|||
switch (SetupPacket.bmRequestType.BM.Type) { |
|||
|
|||
case REQUEST_STANDARD: |
|||
goto stall_i; |
|||
/* not supported */ |
|||
|
|||
case REQUEST_CLASS: |
|||
switch (SetupPacket.bmRequestType.BM.Recipient) { |
|||
case REQUEST_TO_DEVICE: |
|||
goto stall_i; |
|||
/* not supported */ |
|||
|
|||
case REQUEST_TO_INTERFACE: |
|||
if ((SetupPacket.wIndex.WB.L == USB_CDC_CIF_NUM) || /* IF number correct? */ |
|||
(SetupPacket.wIndex.WB.L == USB_CDC_DIF_NUM)) { |
|||
switch (SetupPacket.bRequest) { |
|||
case CDC_SEND_ENCAPSULATED_COMMAND: |
|||
if (CDC_SendEncapsulatedCommand()) { |
|||
USB_StatusInStage(); /* send Acknowledge */ |
|||
goto out_class_ok; |
|||
} |
|||
break; |
|||
case CDC_SET_COMM_FEATURE: |
|||
if (CDC_SetCommFeature(SetupPacket.wValue.W)) { |
|||
USB_StatusInStage(); /* send Acknowledge */ |
|||
goto out_class_ok; |
|||
} |
|||
break; |
|||
case CDC_SET_LINE_CODING: |
|||
if (CDC_SetLineCoding()) { |
|||
USB_StatusInStage(); /* send Acknowledge */ |
|||
goto out_class_ok; |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
goto stall_i; |
|||
/* end case REQUEST_TO_INTERFACE */ |
|||
|
|||
case REQUEST_TO_ENDPOINT: |
|||
goto stall_i; |
|||
/* end case REQUEST_TO_ENDPOINT */ |
|||
|
|||
default: |
|||
goto stall_i; |
|||
} |
|||
out_class_ok: /* request finished successfully */ |
|||
break; /* end case REQUEST_CLASS */ |
|||
default: |
|||
goto stall_i; |
|||
} |
|||
} |
|||
} |
|||
} else { |
|||
USB_StatusOutStage(); /* receive Acknowledge */ |
|||
} |
|||
break; /* end case USB_EVT_OUT */ |
|||
|
|||
case USB_EVT_IN: |
|||
if (SetupPacket.bmRequestType.BM.Dir == REQUEST_DEVICE_TO_HOST) { |
|||
USB_DataInStage(); /* send data */ |
|||
} else { |
|||
if (USB_DeviceAddress & 0x80) { |
|||
USB_DeviceAddress &= 0x7F; |
|||
USB_SetAddress(USB_DeviceAddress); |
|||
} |
|||
} |
|||
break; /* end case USB_EVT_IN */ |
|||
|
|||
case USB_EVT_OUT_STALL: |
|||
USB_ClrStallEP(0x00); |
|||
break; |
|||
|
|||
case USB_EVT_IN_STALL: |
|||
USB_ClrStallEP(0x80); |
|||
break; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,52 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: usbcore.h |
|||
* Purpose: USB Core Definitions |
|||
* Version: V1.20 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC microcontroller devices only. Nothing else |
|||
* gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
#ifndef __USBCORE_H__ |
|||
#define __USBCORE_H__ |
|||
|
|||
|
|||
/* USB Endpoint Data Structure */ |
|||
typedef struct _USB_EP_DATA { |
|||
uint8_t *pData; |
|||
uint16_t Count; |
|||
} USB_EP_DATA; |
|||
|
|||
/* USB Core Global Variables */ |
|||
extern uint16_t USB_DeviceStatus; |
|||
extern uint8_t USB_DeviceAddress; |
|||
extern uint8_t USB_Configuration; |
|||
extern uint32_t USB_EndPointMask; |
|||
extern uint32_t USB_EndPointHalt; |
|||
extern uint32_t USB_EndPointStall; |
|||
extern uint8_t USB_AltSetting[USB_IF_NUM]; |
|||
|
|||
/* USB Endpoint 0 Buffer */ |
|||
extern uint8_t EP0Buf[USB_MAX_PACKET0]; |
|||
|
|||
/* USB Endpoint 0 Data Info */ |
|||
extern USB_EP_DATA EP0Data; |
|||
|
|||
/* USB Setup Packet */ |
|||
extern USB_SETUP_PACKET SetupPacket; |
|||
|
|||
/* USB Core Functions */ |
|||
extern void USB_ResetCore (void); |
|||
|
|||
|
|||
|
|||
#endif /* __USBCORE_H__ */ |
@ -0,0 +1,257 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: usbdesc.c |
|||
* Purpose: USB Descriptors |
|||
* Version: V1.20 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC microcontroller devices only. Nothing else |
|||
* gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------- |
|||
* History: |
|||
* V1.20 Changed string descriptor handling |
|||
* V1.00 Initial Version |
|||
*---------------------------------------------------------------------------*/ |
|||
extern "C" { |
|||
#include "lpc_types.h" |
|||
} |
|||
|
|||
#include "usb.h" |
|||
#include "cdc.h" |
|||
#include "msc.h" |
|||
#include "usbcfg.h" |
|||
#include "usbdesc.h" |
|||
|
|||
|
|||
/* USB Standard Device Descriptor */ |
|||
const uint8_t USB_DeviceDescriptor[] = { |
|||
USB_DEVICE_DESC_SIZE, /* bLength */ |
|||
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
WBVAL(0x0200), /* 2.0 */ /* bcdUSB */ |
|||
USB_DEVICE_CLASS_MISCELLANEOUS, /* bDeviceClass Composite*/ |
|||
0x02, /* bDeviceSubClass */ |
|||
0x01, /* bDeviceProtocol */ |
|||
USB_MAX_PACKET0, /* bMaxPacketSize0 */ |
|||
WBVAL(0x1d50), /* idVendor */ |
|||
WBVAL(0x6029), /* idProduct */ |
|||
WBVAL(0x0100), /* 1.00 */ /* bcdDevice */ |
|||
0x01, /* iManufacturer */ |
|||
0x02, /* iProduct */ |
|||
0x03, /* iSerialNumber */ |
|||
0x01 /* bNumConfigurations: one possible configuration*/ |
|||
}; |
|||
|
|||
/* USB Configuration Descriptor */ |
|||
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */ |
|||
const uint8_t USB_ConfigDescriptor[] = { |
|||
/* Configuration 1 */ |
|||
USB_CONFIGUARTION_DESC_SIZE, /* bLength */ |
|||
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
WBVAL( /* wTotalLength */ |
|||
1*USB_CONFIGUARTION_DESC_SIZE + |
|||
// Interface Association Descriptor
|
|||
8 + |
|||
//CDC Control Interface
|
|||
1*USB_INTERFACE_DESC_SIZE + /* communication interface */ |
|||
0x0013 + /* CDC functions */ |
|||
1*USB_ENDPOINT_DESC_SIZE + /* interrupt endpoint */ |
|||
//CDC Data Interface
|
|||
1*USB_INTERFACE_DESC_SIZE + /* data interface */ |
|||
2*USB_ENDPOINT_DESC_SIZE + /* bulk endpoints */ |
|||
//MSC Interface
|
|||
1*USB_INTERFACE_DESC_SIZE + |
|||
2*USB_ENDPOINT_DESC_SIZE |
|||
), |
|||
0x03, /* bNumInterfaces */ |
|||
0x01, /* bConfigurationValue: 0x01 is used to select this configuration */ |
|||
0x00, /* iConfiguration: no string to describe this configuration */ |
|||
USB_CONFIG_BUS_POWERED, /* bmAttributes */ |
|||
USB_CONFIG_POWER_MA(500), /* bMaxPower, device power consumption is 500 mA */ |
|||
|
|||
|
|||
/* Interface Association Descriptor */ |
|||
0x08, |
|||
0x0B, //DescriptorType : Interface Association
|
|||
0x00, //FirstInterface
|
|||
0x02, //InterfaceCount
|
|||
0x02, //FunctionClass
|
|||
0x02, //FunctionSubClass
|
|||
0x01, //FunctionProtocol
|
|||
0x00, //Function
|
|||
|
|||
/* Interface 0, Alternate Setting 0, Communication class interface descriptor */ |
|||
USB_INTERFACE_DESC_SIZE, /* bLength */ |
|||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
USB_CDC_CIF_NUM, /* bInterfaceNumber: Number of Interface */ |
|||
0x00, /* bAlternateSetting: Alternate setting */ |
|||
0x01, /* bNumEndpoints: One endpoint used */ |
|||
CDC_COMMUNICATION_INTERFACE_CLASS, /* bInterfaceClass: Communication Interface Class */ |
|||
CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass: Abstract Control Model */ |
|||
0x00, /* bInterfaceProtocol: no protocol used */ |
|||
0x00, /* iInterface: */ |
|||
|
|||
/*Header Functional Descriptor*/ |
|||
0x05, /* bLength: Endpoint Descriptor size */ |
|||
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */ |
|||
CDC_HEADER, /* bDescriptorSubtype: Header Func Desc */ |
|||
WBVAL(CDC_V1_10), /* 1.10 */ /* bcdCDC */ |
|||
|
|||
/*Call Management Functional Descriptor*/ |
|||
0x05, /* bFunctionLength */ |
|||
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */ |
|||
CDC_CALL_MANAGEMENT, /* bDescriptorSubtype: Call Management Func Desc */ |
|||
CDC_CALLMGMT_CAP_CALLMGMT | CDC_CALLMGMT_CAP_DATAINTF, /* bmCapabilities: device handles call management */ |
|||
0x01, /* bDataInterface: CDC data IF ID */ |
|||
|
|||
/*Abstract Control Management Functional Descriptor*/ |
|||
0x04, /* bFunctionLength */ |
|||
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */ |
|||
CDC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype: Abstract Control Management desc */ |
|||
CDC_ACM_CAP_LINE | CDC_ACM_CAP_BRK,/* bmCapabilities: SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported */ |
|||
|
|||
/*Union Functional Descriptor*/ |
|||
0x05, /* bFunctionLength */ |
|||
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */ |
|||
CDC_UNION, /* bDescriptorSubtype: Union func desc */ |
|||
USB_CDC_CIF_NUM, /* bMasterInterface: Communication class interface is master */ |
|||
USB_CDC_DIF_NUM, /* bSlaveInterface0: Data class interface is slave 0 */ |
|||
|
|||
/*Endpoint 1 Descriptor*/ /* event notification (optional) */ |
|||
USB_ENDPOINT_DESC_SIZE, /* bLength */ |
|||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
USB_ENDPOINT_IN(1), /* bEndpointAddress */ |
|||
USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ |
|||
WBVAL(0x0010), /* wMaxPacketSize */ |
|||
0x10, /* bInterval */ |
|||
|
|||
|
|||
/* Interface 1, Alternate Setting 0, Data class interface descriptor*/ |
|||
USB_INTERFACE_DESC_SIZE, /* bLength */ |
|||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
USB_CDC_DIF_NUM, /* bInterfaceNumber: Number of Interface */ |
|||
0x00, /* bAlternateSetting: no alternate setting */ |
|||
0x02, /* bNumEndpoints: two endpoints used */ |
|||
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass: Data Interface Class */ |
|||
0x00, /* bInterfaceSubClass: no subclass available */ |
|||
0x00, /* bInterfaceProtocol: no protocol used */ |
|||
0x00, /* iInterface: */ |
|||
/* Endpoint, EP2 Bulk Out */ |
|||
USB_ENDPOINT_DESC_SIZE, /* bLength */ |
|||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
USB_ENDPOINT_OUT(2), /* bEndpointAddress */ |
|||
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ |
|||
WBVAL(USB_CDC_BUFSIZE), /* wMaxPacketSize */ |
|||
0x00, /* bInterval: ignore for Bulk transfer */ |
|||
/* Endpoint, EP2 Bulk In */ |
|||
USB_ENDPOINT_DESC_SIZE, /* bLength */ |
|||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
USB_ENDPOINT_IN(2), /* bEndpointAddress */ |
|||
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ |
|||
WBVAL(USB_CDC_BUFSIZE), /* wMaxPacketSize */ |
|||
0x00, /* bInterval: ignore for Bulk transfer */ |
|||
|
|||
|
|||
/* MSC Interface */ |
|||
/* Interface 2, Alternate Setting 0, Data class interface descriptor*/ |
|||
USB_INTERFACE_DESC_SIZE, /* bLength */ |
|||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
0x02, /* bInterfaceNumber */ |
|||
0x00, /* bAlternateSetting */ |
|||
0x02, /* bNumEndpoints */ |
|||
USB_DEVICE_CLASS_STORAGE, /* bInterfaceClass */ |
|||
MSC_SUBCLASS_SCSI, /* bInterfaceSubClass */ |
|||
MSC_PROTOCOL_BULK_ONLY, /* bInterfaceProtocol */ |
|||
0x00, /* iInterface */ |
|||
/* Bulk In Endpoint */ |
|||
USB_ENDPOINT_DESC_SIZE, /* bLength */ |
|||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
USB_ENDPOINT_IN(5), /* bEndpointAddress */ |
|||
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ |
|||
WBVAL(0x0040), /* wMaxPacketSize */ |
|||
0x00, /* bInterval */ |
|||
/* Bulk Out Endpoint */ |
|||
USB_ENDPOINT_DESC_SIZE, /* bLength */ |
|||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
USB_ENDPOINT_OUT(5), /* bEndpointAddress */ |
|||
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ |
|||
WBVAL(0x0040), /* wMaxPacketSize */ |
|||
0, |
|||
/* Terminator */ |
|||
0 /* bLength */ |
|||
}; |
|||
|
|||
|
|||
|
|||
|
|||
/* USB String Descriptor (optional) */ |
|||
const uint8_t USB_StringDescriptor[] = { |
|||
/* Index 0x00: LANGID Codes */ |
|||
0x04, /* bLength */ |
|||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
WBVAL(0x0409), /* US English */ /* wLANGID */ |
|||
/* Index 0x01: Manufacturer */ |
|||
(13*2 + 2), /* bLength (13 Char + Type + length) */ |
|||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
'm',0, |
|||
'a',0, |
|||
'r',0, |
|||
'l',0, |
|||
'i',0, |
|||
'n',0, |
|||
'f',0, |
|||
'w',0, |
|||
'.',0, |
|||
'o',0, |
|||
'r',0, |
|||
'g',0, |
|||
' ',0, |
|||
/* Index 0x02: Product */ |
|||
(17*2 + 2), /* bLength ( 17 Char + Type + length) */ |
|||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
'M',0, |
|||
'a',0, |
|||
'r',0, |
|||
'l',0, |
|||
'i',0, |
|||
'n',0, |
|||
' ',0, |
|||
'U',0, |
|||
'S',0, |
|||
'B',0, |
|||
' ',0, |
|||
'D',0, |
|||
'e',0, |
|||
'v',0, |
|||
'i',0, |
|||
'c',0, |
|||
'e',0, |
|||
/* Index 0x03: Serial Number */ |
|||
(12*2 + 2), /* bLength (12 Char + Type + length) */ |
|||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
'1',0, |
|||
'.',0, |
|||
'0',0, |
|||
'0',0, |
|||
'0',0, |
|||
'0',0, |
|||
'0',0, |
|||
'0',0, |
|||
'0',0, |
|||
'0',0, |
|||
'0',0, |
|||
'0',0, |
|||
/* Index 0x04: Interface 0, Alternate Setting 0 */ |
|||
( 4*2 + 2), /* bLength (4 Char + Type + length) */ |
|||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ |
|||
'V',0, |
|||
'C',0, |
|||
'O',0, |
|||
'M',0, |
|||
}; |
@ -0,0 +1,35 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: usbdesc.h |
|||
* Purpose: USB Descriptors Definitions |
|||
* Version: V1.20 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC microcontroller devices only. Nothing else |
|||
* gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
#ifndef __USBDESC_H__ |
|||
#define __USBDESC_H__ |
|||
|
|||
|
|||
#define WBVAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF) |
|||
|
|||
#define USB_DEVICE_DESC_SIZE (sizeof(USB_DEVICE_DESCRIPTOR)) |
|||
#define USB_CONFIGUARTION_DESC_SIZE (sizeof(USB_CONFIGURATION_DESCRIPTOR)) |
|||
#define USB_INTERFACE_DESC_SIZE (sizeof(USB_INTERFACE_DESCRIPTOR)) |
|||
#define USB_ENDPOINT_DESC_SIZE (sizeof(USB_ENDPOINT_DESCRIPTOR)) |
|||
|
|||
extern const uint8_t USB_DeviceDescriptor[]; |
|||
extern const uint8_t USB_ConfigDescriptor[]; |
|||
extern const uint8_t USB_StringDescriptor[]; |
|||
|
|||
|
|||
#endif /* __USBDESC_H__ */ |
@ -0,0 +1,811 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: usbhw.c |
|||
* Purpose: USB Hardware Layer Module for NXP's LPC17xx MCU |
|||
* Version: V1.20 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC family microcontroller devices only. Nothing |
|||
* else gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------- |
|||
* History: |
|||
* V1.20 Added USB_ClearEPBuf |
|||
* V1.00 Initial Version |
|||
*----------------------------------------------------------------------------*/ |
|||
extern "C" { |
|||
#include "LPC17xx.h" /* LPC17xx definitions */ |
|||
} |
|||
|
|||
#include "usb.h" |
|||
#include "usbcfg.h" |
|||
#include "usbreg.h" |
|||
#include "usbhw.h" |
|||
#include "usbcore.h" |
|||
#include "usbuser.h" |
|||
|
|||
#define EP_MSK_CTRL 0x0001 /* Control Endpoint Logical Address Mask */ |
|||
#define EP_MSK_BULK 0xC924 /* Bulk Endpoint Logical Address Mask */ |
|||
#define EP_MSK_INT 0x4492 /* Interrupt Endpoint Logical Address Mask */ |
|||
#define EP_MSK_ISO 0x1248 /* Isochronous Endpoint Logical Address Mask */ |
|||
|
|||
#if USB_DMA |
|||
uint32_t UDCA[USB_EP_NUM] __attribute__((section("USB_RAM"))); /* UDCA in USB RAM */ |
|||
uint32_t DD_NISO_Mem[4*DD_NISO_CNT] __attribute__((section("USB_RAM"))); /* Non-Iso DMA Descriptor Memory */ |
|||
uint32_t DD_ISO_Mem [5*DD_ISO_CNT] __attribute__((section("USB_RAM"))); /* Iso DMA Descriptor Memory */ |
|||
uint32_t udca[USB_EP_NUM]; /* UDCA saved values */ |
|||
uint32_t DDMemMap[2]; |
|||
#endif |
|||
|
|||
|
|||
/*
|
|||
* Get Endpoint Physical Address |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* Return Value: Endpoint Physical Address |
|||
*/ |
|||
|
|||
uint32_t EPAdr (uint32_t EPNum) { |
|||
uint32_t val; |
|||
|
|||
val = (EPNum & 0x0F) << 1; |
|||
if (EPNum & 0x80) { |
|||
val += 1; |
|||
} |
|||
return (val); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Write Command |
|||
* Parameters: cmd: Command |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void WrCmd (uint32_t cmd) { |
|||
|
|||
LPC_USB->USBDevIntClr = CCEMTY_INT; |
|||
LPC_USB->USBCmdCode = cmd; |
|||
while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Write Command Data |
|||
* Parameters: cmd: Command |
|||
* val: Data |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void WrCmdDat (uint32_t cmd, uint32_t val) { |
|||
|
|||
LPC_USB->USBDevIntClr = CCEMTY_INT; |
|||
LPC_USB->USBCmdCode = cmd; |
|||
while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0); |
|||
LPC_USB->USBDevIntClr = CCEMTY_INT; |
|||
LPC_USB->USBCmdCode = val; |
|||
while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Write Command to Endpoint |
|||
* Parameters: cmd: Command |
|||
* val: Data |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void WrCmdEP (uint32_t EPNum, uint32_t cmd){ |
|||
|
|||
LPC_USB->USBDevIntClr = CCEMTY_INT; |
|||
LPC_USB->USBCmdCode = CMD_SEL_EP(EPAdr(EPNum)); |
|||
while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0); |
|||
LPC_USB->USBDevIntClr = CCEMTY_INT; |
|||
LPC_USB->USBCmdCode = cmd; |
|||
while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Read Command Data |
|||
* Parameters: cmd: Command |
|||
* Return Value: Data Value |
|||
*/ |
|||
|
|||
uint32_t RdCmdDat (uint32_t cmd) { |
|||
|
|||
LPC_USB->USBDevIntClr = CCEMTY_INT | CDFULL_INT; |
|||
LPC_USB->USBCmdCode = cmd; |
|||
while ((LPC_USB->USBDevIntSt & CDFULL_INT) == 0); |
|||
return (LPC_USB->USBCmdData); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Initialize Function |
|||
* Called by the User to initialize USB |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_Init (void) { |
|||
|
|||
LPC_PINCON->PINSEL1 &= ~((3<<26)|(3<<28)); /* P0.29 D+, P0.30 D- */ |
|||
LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); /* PINSEL1 26.27, 28.29 = 01 */ |
|||
|
|||
//todo: VBUS not used by smoothieboard (though spec requires it for self powered devices), pin used for beeper
|
|||
//todo: Goodlink used for servo4?
|
|||
//LPC_PINCON->PINSEL3 &= ~((3<< 4)|(3<<28)); /* P1.18 GoodLink, P1.30 VBUS */
|
|||
//LPC_PINCON->PINSEL3 |= ((1<< 4)|(2<<28)); /* PINSEL3 4.5 = 01, 28.29 = 10 */
|
|||
|
|||
LPC_PINCON->PINSEL4 &= ~((3<<18) ); /* P2.9 SoftConnect */ |
|||
LPC_PINCON->PINSEL4 |= ((1<<18) ); /* PINSEL4 18.19 = 01 */ |
|||
|
|||
LPC_SC->PCONP |= (1UL<<31); /* USB PCLK -> enable USB Per. */ |
|||
|
|||
LPC_USB->USBClkCtrl = 0x1A; /* Dev, PortSel, AHB clock enable */ |
|||
while ((LPC_USB->USBClkSt & 0x1A) != 0x1A); |
|||
|
|||
NVIC_EnableIRQ(USB_IRQn); /* enable USB interrupt */ |
|||
|
|||
USB_Reset(); |
|||
USB_SetAddress(0); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Connect Function |
|||
* Called by the User to Connect/Disconnect USB |
|||
* Parameters: con: Connect/Disconnect |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_Connect (uint32_t con) { |
|||
WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(con ? DEV_CON : 0)); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Reset Function |
|||
* Called automatically on USB Reset |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_Reset (void) { |
|||
#if USB_DMA |
|||
uint32_t n; |
|||
#endif |
|||
|
|||
LPC_USB->USBEpInd = 0; |
|||
LPC_USB->USBMaxPSize = USB_MAX_PACKET0; |
|||
LPC_USB->USBEpInd = 1; |
|||
LPC_USB->USBMaxPSize = USB_MAX_PACKET0; |
|||
while ((LPC_USB->USBDevIntSt & EP_RLZED_INT) == 0); |
|||
|
|||
LPC_USB->USBEpIntClr = 0xFFFFFFFF; |
|||
LPC_USB->USBEpIntEn = 0xFFFFFFFF ^ USB_DMA_EP; |
|||
LPC_USB->USBDevIntClr = 0xFFFFFFFF; |
|||
LPC_USB->USBDevIntEn = DEV_STAT_INT | EP_SLOW_INT | |
|||
(USB_SOF_EVENT ? FRAME_INT : 0) | |
|||
(USB_ERROR_EVENT ? ERR_INT : 0); |
|||
|
|||
WrCmdDat(CMD_SET_MODE, DAT_WR_BYTE(INAK_BI)); |
|||
|
|||
|
|||
#if USB_DMA |
|||
LPC_USB->USBUDCAH = USB_RAM_ADR; |
|||
LPC_USB->USBDMARClr = 0xFFFFFFFF; |
|||
LPC_USB->USBEpDMADis = 0xFFFFFFFF; |
|||
LPC_USB->USBEpDMAEn = USB_DMA_EP; |
|||
LPC_USB->USBEoTIntClr = 0xFFFFFFFF; |
|||
LPC_USB->USBNDDRIntClr = 0xFFFFFFFF; |
|||
LPC_USB->USBSysErrIntClr = 0xFFFFFFFF; |
|||
LPC_USB->USBDMAIntEn = 0x00000007; |
|||
DDMemMap[0] = 0x00000000; |
|||
DDMemMap[1] = 0x00000000; |
|||
for (n = 0; n < USB_EP_NUM; n++) { |
|||
udca[n] = 0; |
|||
UDCA[n] = 0; |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Suspend Function |
|||
* Called automatically on USB Suspend |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_Suspend (void) { |
|||
/* Performed by Hardware */ |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Resume Function |
|||
* Called automatically on USB Resume |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_Resume (void) { |
|||
/* Performed by Hardware */ |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Remote Wakeup Function |
|||
* Called automatically on USB Remote Wakeup |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_WakeUp (void) { |
|||
|
|||
if (USB_DeviceStatus & USB_GETSTATUS_REMOTE_WAKEUP) { |
|||
WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(DEV_CON)); |
|||
} |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Remote Wakeup Configuration Function |
|||
* Parameters: cfg: Enable/Disable |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_WakeUpCfg (uint32_t cfg) { |
|||
/* Not needed */ |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Set Address Function |
|||
* Parameters: adr: USB Address |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_SetAddress (uint32_t adr) { |
|||
WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /* Don't wait for next */ |
|||
WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /* Setup Status Phase */ |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Configure Function |
|||
* Parameters: cfg: Configure/Deconfigure |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_Configure (uint32_t cfg) { |
|||
|
|||
WrCmdDat(CMD_CFG_DEV, DAT_WR_BYTE(cfg ? CONF_DVICE : 0)); |
|||
|
|||
LPC_USB->USBReEp = 0x00000003; |
|||
while ((LPC_USB->USBDevIntSt & EP_RLZED_INT) == 0); |
|||
LPC_USB->USBDevIntClr = EP_RLZED_INT; |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Configure USB Endpoint according to Descriptor |
|||
* Parameters: pEPD: Pointer to Endpoint Descriptor |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD) { |
|||
uint32_t num; |
|||
|
|||
num = EPAdr(pEPD->bEndpointAddress); |
|||
LPC_USB->USBReEp |= (1 << num); |
|||
LPC_USB->USBEpInd = num; |
|||
LPC_USB->USBMaxPSize = pEPD->wMaxPacketSize; |
|||
while ((LPC_USB->USBDevIntSt & EP_RLZED_INT) == 0); |
|||
LPC_USB->USBDevIntClr = EP_RLZED_INT; |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Set Direction for USB Control Endpoint |
|||
* Parameters: dir: Out (dir == 0), In (dir <> 0) |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_DirCtrlEP (uint32_t dir) { |
|||
/* Not needed */ |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Enable USB Endpoint |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_EnableEP (uint32_t EPNum) { |
|||
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0)); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Disable USB Endpoint |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_DisableEP (uint32_t EPNum) { |
|||
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_DA)); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Reset USB Endpoint |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_ResetEP (uint32_t EPNum) { |
|||
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0)); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Set Stall for USB Endpoint |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_SetStallEP (uint32_t EPNum) { |
|||
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_ST)); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Clear Stall for USB Endpoint |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_ClrStallEP (uint32_t EPNum) { |
|||
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0)); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Clear USB Endpoint Buffer |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_ClearEPBuf (uint32_t EPNum) { |
|||
WrCmdEP(EPNum, CMD_CLR_BUF); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Read USB Endpoint Data |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* pData: Pointer to Data Buffer |
|||
* Return Value: Number of bytes read |
|||
*/ |
|||
|
|||
uint32_t USB_ReadEP (uint32_t EPNum, uint8_t *pData) { |
|||
uint32_t cnt, n; |
|||
|
|||
LPC_USB->USBCtrl = ((EPNum & 0x0F) << 2) | CTRL_RD_EN; |
|||
|
|||
do { |
|||
cnt = LPC_USB->USBRxPLen; |
|||
} while ((cnt & PKT_RDY) == 0); |
|||
cnt &= PKT_LNGTH_MASK; |
|||
|
|||
for (n = 0; n < (cnt + 3) / 4; n++) { |
|||
*((__packed uint32_t *)pData) = LPC_USB->USBRxData; |
|||
pData += 4; |
|||
} |
|||
LPC_USB->USBCtrl = 0; |
|||
|
|||
if (((EP_MSK_ISO >> EPNum) & 1) == 0) { /* Non-Isochronous Endpoint */ |
|||
WrCmdEP(EPNum, CMD_CLR_BUF); |
|||
} |
|||
|
|||
return (cnt); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Write USB Endpoint Data |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* pData: Pointer to Data Buffer |
|||
* cnt: Number of bytes to write |
|||
* Return Value: Number of bytes written |
|||
*/ |
|||
|
|||
uint32_t USB_WriteEP (uint32_t EPNum, uint8_t *pData, uint32_t cnt) { |
|||
uint32_t n; |
|||
|
|||
LPC_USB->USBCtrl = ((EPNum & 0x0F) << 2) | CTRL_WR_EN; |
|||
|
|||
LPC_USB->USBTxPLen = cnt; |
|||
|
|||
for (n = 0; n < (cnt + 3) / 4; n++) { |
|||
LPC_USB->USBTxData = *((__packed uint32_t *)pData); |
|||
pData += 4; |
|||
} |
|||
LPC_USB->USBCtrl = 0; |
|||
WrCmdEP(EPNum, CMD_VALID_BUF); |
|||
return (cnt); |
|||
} |
|||
|
|||
#if USB_DMA |
|||
|
|||
/* DMA Descriptor Memory Layout */ |
|||
const uint32_t DDAdr[2] = { DD_NISO_ADR, DD_ISO_ADR }; |
|||
const uint32_t DDSz [2] = { 16, 20 }; |
|||
|
|||
|
|||
/*
|
|||
* Setup USB DMA Transfer for selected Endpoint |
|||
* Parameters: EPNum: Endpoint Number |
|||
* pDD: Pointer to DMA Descriptor |
|||
* Return Value: TRUE - Success, FALSE - Error |
|||
*/ |
|||
|
|||
uint32_t USB_DMA_Setup(uint32_t EPNum, USB_DMA_DESCRIPTOR *pDD) { |
|||
uint32_t num, ptr, nxt, iso, n; |
|||
|
|||
iso = pDD->Cfg.Type.IsoEP; /* Iso or Non-Iso Descriptor */ |
|||
num = EPAdr(EPNum); /* Endpoint's Physical Address */ |
|||
|
|||
ptr = 0; /* Current Descriptor */ |
|||
nxt = udca[num]; /* Initial Descriptor */ |
|||
while (nxt) { /* Go through Descriptor List */ |
|||
ptr = nxt; /* Current Descriptor */ |
|||
if (!pDD->Cfg.Type.Link) { /* Check for Linked Descriptors */ |
|||
n = (ptr - DDAdr[iso]) / DDSz[iso]; /* Descriptor Index */ |
|||
DDMemMap[iso] &= ~(1 << n); /* Unmark Memory Usage */ |
|||
} |
|||
nxt = *((uint32_t *)ptr); /* Next Descriptor */ |
|||
} |
|||
|
|||
for (n = 0; n < 32; n++) { /* Search for available Memory */ |
|||
if ((DDMemMap[iso] & (1 << n)) == 0) { |
|||
break; /* Memory found */ |
|||
} |
|||
} |
|||
if (n == 32) return (FALSE); /* Memory not available */ |
|||
|
|||
DDMemMap[iso] |= 1 << n; /* Mark Memory Usage */ |
|||
nxt = DDAdr[iso] + n * DDSz[iso]; /* Next Descriptor */ |
|||
|
|||
if (ptr && pDD->Cfg.Type.Link) { |
|||
*((uint32_t *)(ptr + 0)) = nxt; /* Link in new Descriptor */ |
|||
*((uint32_t *)(ptr + 4)) |= 0x00000004; /* Next DD is Valid */ |
|||
} else { |
|||
udca[num] = nxt; /* Save new Descriptor */ |
|||
UDCA[num] = nxt; /* Update UDCA in USB */ |
|||
} |
|||
|
|||
uint32_t * nxt_ptr = (uint32_t *)nxt; |
|||
/* Fill in DMA Descriptor */ |
|||
*nxt_ptr++ = 0; /* Next DD Pointer */ |
|||
*nxt_ptr++ = (pDD->Cfg.Type.ATLE) | |
|||
(pDD->Cfg.Type.IsoEP << 4) | |
|||
(pDD->MaxSize << 5) | |
|||
(pDD->BufLen << 16); |
|||
*nxt_ptr++ = pDD->BufAdr; |
|||
*nxt_ptr++ = pDD->Cfg.Type.LenPos << 8; |
|||
if (iso) { |
|||
*nxt_ptr = pDD->InfoAdr; |
|||
} |
|||
|
|||
return (TRUE); /* Success */ |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Enable USB DMA Endpoint |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_DMA_Enable (uint32_t EPNum) { |
|||
LPC_USB->USBEpDMAEn = 1 << EPAdr(EPNum); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Disable USB DMA Endpoint |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* Return Value: None |
|||
*/ |
|||
|
|||
void USB_DMA_Disable (uint32_t EPNum) { |
|||
LPC_USB->USBEpDMADis = 1 << EPAdr(EPNum); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Get USB DMA Endpoint Status |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* Return Value: DMA Status |
|||
*/ |
|||
|
|||
uint32_t USB_DMA_Status (uint32_t EPNum) { |
|||
uint32_t ptr, val; |
|||
|
|||
ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */ |
|||
if (ptr == 0) |
|||
return (USB_DMA_INVALID); |
|||
|
|||
val = *((uint32_t *)(ptr + 3*4)); /* Status Information */ |
|||
switch ((val >> 1) & 0x0F) { |
|||
case 0x00: /* Not serviced */ |
|||
return (USB_DMA_IDLE); |
|||
case 0x01: /* Being serviced */ |
|||
return (USB_DMA_BUSY); |
|||
case 0x02: /* Normal Completition */ |
|||
return (USB_DMA_DONE); |
|||
case 0x03: /* Data Under Run */ |
|||
return (USB_DMA_UNDER_RUN); |
|||
case 0x08: /* Data Over Run */ |
|||
return (USB_DMA_OVER_RUN); |
|||
case 0x09: /* System Error */ |
|||
return (USB_DMA_ERROR); |
|||
} |
|||
|
|||
return (USB_DMA_UNKNOWN); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Get USB DMA Endpoint Current Buffer Address |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* Return Value: DMA Address (or -1 when DMA is Invalid) |
|||
*/ |
|||
|
|||
uint32_t USB_DMA_BufAdr (uint32_t EPNum) { |
|||
uint32_t ptr, val; |
|||
|
|||
ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */ |
|||
if (ptr == 0) |
|||
{ |
|||
return ((uint32_t)(-1)); /* DMA Invalid */ |
|||
} |
|||
|
|||
val = *((uint32_t *)(ptr + 2*4)); /* Buffer Address */ |
|||
return (val); /* Current Address */ |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Get USB DMA Endpoint Current Buffer Count |
|||
* Number of transfered Bytes or Iso Packets |
|||
* Parameters: EPNum: Endpoint Number |
|||
* EPNum.0..3: Address |
|||
* EPNum.7: Dir |
|||
* Return Value: DMA Count (or -1 when DMA is Invalid) |
|||
*/ |
|||
|
|||
uint32_t USB_DMA_BufCnt (uint32_t EPNum) { |
|||
uint32_t ptr, val; |
|||
|
|||
ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */ |
|||
if (ptr == 0) |
|||
{ |
|||
return ((uint32_t)(-1)); /* DMA Invalid */ |
|||
} |
|||
val = *((uint32_t *)(ptr + 3*4)); /* Status Information */ |
|||
return (val >> 16); /* Current Count */ |
|||
} |
|||
|
|||
|
|||
#endif /* USB_DMA */ |
|||
|
|||
|
|||
/*
|
|||
* Get USB Last Frame Number |
|||
* Parameters: None |
|||
* Return Value: Frame Number |
|||
*/ |
|||
|
|||
uint32_t USB_GetFrame (void) { |
|||
uint32_t val; |
|||
|
|||
WrCmd(CMD_RD_FRAME); |
|||
val = RdCmdDat(DAT_RD_FRAME); |
|||
val = val | (RdCmdDat(DAT_RD_FRAME) << 8); |
|||
|
|||
return (val); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Interrupt Service Routine |
|||
*/ |
|||
|
|||
void USB_IRQHandler (void) { |
|||
uint32_t disr, val, n, m; |
|||
uint32_t episr, episrCur; |
|||
|
|||
disr = LPC_USB->USBDevIntSt; /* Device Interrupt Status */ |
|||
|
|||
/* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */ |
|||
if (disr & DEV_STAT_INT) { |
|||
LPC_USB->USBDevIntClr = DEV_STAT_INT; |
|||
WrCmd(CMD_GET_DEV_STAT); |
|||
val = RdCmdDat(DAT_GET_DEV_STAT); /* Device Status */ |
|||
if (val & DEV_RST) { /* Reset */ |
|||
USB_Reset(); |
|||
#if USB_RESET_EVENT |
|||
USB_Reset_Event(); |
|||
#endif |
|||
} |
|||
if (val & DEV_CON_CH) { /* Connect change */ |
|||
#if USB_POWER_EVENT |
|||
USB_Power_Event(val & DEV_CON); |
|||
#endif |
|||
} |
|||
if (val & DEV_SUS_CH) { /* Suspend/Resume */ |
|||
if (val & DEV_SUS) { /* Suspend */ |
|||
USB_Suspend(); |
|||
#if USB_SUSPEND_EVENT |
|||
USB_Suspend_Event(); |
|||
#endif |
|||
} else { /* Resume */ |
|||
USB_Resume(); |
|||
#if USB_RESUME_EVENT |
|||
USB_Resume_Event(); |
|||
#endif |
|||
} |
|||
} |
|||
goto isr_end; |
|||
} |
|||
|
|||
#if USB_SOF_EVENT |
|||
/* Start of Frame Interrupt */ |
|||
if (disr & FRAME_INT) { |
|||
LPC_USB->USBDevIntClr = FRAME_INT; |
|||
USB_SOF_Event(); |
|||
} |
|||
#endif |
|||
|
|||
#if USB_ERROR_EVENT |
|||
/* Error Interrupt */ |
|||
if (disr & ERR_INT) { |
|||
LPC_USB->USBDevIntClr = ERR_INT; |
|||
WrCmd(CMD_RD_ERR_STAT); |
|||
val = RdCmdDat(DAT_RD_ERR_STAT); |
|||
USB_Error_Event(val); |
|||
} |
|||
#endif |
|||
|
|||
/* Endpoint's Slow Interrupt */ |
|||
if (disr & EP_SLOW_INT) { |
|||
episrCur = 0; |
|||
episr = LPC_USB->USBEpIntSt; |
|||
for (n = 0; n < USB_EP_NUM; n++) { /* Check All Endpoints */ |
|||
if (episr == episrCur) break; /* break if all EP interrupts handled */ |
|||
if (episr & (1 << n)) { |
|||
episrCur |= (1 << n); |
|||
m = n >> 1; |
|||
|
|||
LPC_USB->USBEpIntClr = (1 << n); |
|||
while ((LPC_USB->USBDevIntSt & CDFULL_INT) == 0); |
|||
val = LPC_USB->USBCmdData; |
|||
|
|||
if ((n & 1) == 0) { /* OUT Endpoint */ |
|||
if (n == 0) { /* Control OUT Endpoint */ |
|||
if (val & EP_SEL_STP) { /* Setup Packet */ |
|||
if (USB_P_EP[0]) { |
|||
USB_P_EP[0](USB_EVT_SETUP); |
|||
continue; |
|||
} |
|||
} |
|||
} |
|||
if (USB_P_EP[m]) { |
|||
USB_P_EP[m](USB_EVT_OUT); |
|||
} |
|||
} else { /* IN Endpoint */ |
|||
if (USB_P_EP[m]) { |
|||
USB_P_EP[m](USB_EVT_IN); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
LPC_USB->USBDevIntClr = EP_SLOW_INT; |
|||
} |
|||
|
|||
#if USB_DMA |
|||
|
|||
if (LPC_USB->USBDMAIntSt & 0x00000001) { /* End of Transfer Interrupt */ |
|||
val = LPC_USB->USBEoTIntSt; |
|||
for (n = 2; n < USB_EP_NUM; n++) { /* Check All Endpoints */ |
|||
if (val & (1 << n)) { |
|||
m = n >> 1; |
|||
if ((n & 1) == 0) { /* OUT Endpoint */ |
|||
if (USB_P_EP[m]) { |
|||
USB_P_EP[m](USB_EVT_OUT_DMA_EOT); |
|||
} |
|||
} else { /* IN Endpoint */ |
|||
if (USB_P_EP[m]) { |
|||
USB_P_EP[m](USB_EVT_IN_DMA_EOT); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
LPC_USB->USBEoTIntClr = val; |
|||
} |
|||
|
|||
if (LPC_USB->USBDMAIntSt & 0x00000002) { /* New DD Request Interrupt */ |
|||
val = LPC_USB->USBNDDRIntSt; |
|||
for (n = 2; n < USB_EP_NUM; n++) { /* Check All Endpoints */ |
|||
if (val & (1 << n)) { |
|||
m = n >> 1; |
|||
if ((n & 1) == 0) { /* OUT Endpoint */ |
|||
if (USB_P_EP[m]) { |
|||
USB_P_EP[m](USB_EVT_OUT_DMA_NDR); |
|||
} |
|||
} else { /* IN Endpoint */ |
|||
if (USB_P_EP[m]) { |
|||
USB_P_EP[m](USB_EVT_IN_DMA_NDR); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
LPC_USB->USBNDDRIntClr = val; |
|||
} |
|||
|
|||
if (LPC_USB->USBDMAIntSt & 0x00000004) { /* System Error Interrupt */ |
|||
val = LPC_USB->USBSysErrIntSt; |
|||
for (n = 2; n < USB_EP_NUM; n++) { /* Check All Endpoints */ |
|||
if (val & (1 << n)) { |
|||
m = n >> 1; |
|||
if ((n & 1) == 0) { /* OUT Endpoint */ |
|||
if (USB_P_EP[m]) { |
|||
USB_P_EP[m](USB_EVT_OUT_DMA_ERR); |
|||
} |
|||
} else { /* IN Endpoint */ |
|||
if (USB_P_EP[m]) { |
|||
USB_P_EP[m](USB_EVT_IN_DMA_ERR); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
LPC_USB->USBSysErrIntClr = val; |
|||
} |
|||
|
|||
#endif /* USB_DMA */ |
|||
|
|||
isr_end: |
|||
return; |
|||
} |
@ -0,0 +1,114 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: usbhw.h |
|||
* Purpose: USB Hardware Layer Definitions |
|||
* Version: V1.20 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC family microcontroller devices only. Nothing |
|||
* else gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------- |
|||
* History: |
|||
* V1.20 Added USB_ClearEPBuf |
|||
* V1.00 Initial Version |
|||
*----------------------------------------------------------------------------*/ |
|||
|
|||
#ifndef __USBHW_H__ |
|||
#define __USBHW_H__ |
|||
extern "C" { |
|||
#include "lpc_types.h" |
|||
} |
|||
/* USB RAM Definitions */ |
|||
#define USB_RAM_ADR 0x2007C000 /* USB RAM Start Address */ |
|||
#define USB_RAM_SZ 0x00004000 /* USB RAM Size (16kB) */ |
|||
|
|||
/* DMA Endpoint Descriptors */ |
|||
#define DD_NISO_CNT 16 /* Non-Iso EP DMA Descr. Count (max. 32) */ |
|||
#define DD_ISO_CNT 8 /* Iso EP DMA Descriptor Count (max. 32) */ |
|||
#define DD_NISO_SZ (DD_NISO_CNT * 16) /* Non-Iso DMA Descr. Size */ |
|||
#define DD_ISO_SZ (DD_ISO_CNT * 20) /* Iso DMA Descriptor Size */ |
|||
#define DD_NISO_ADR (USB_RAM_ADR + 128) /* Non-Iso DMA Descr. Address */ |
|||
#define DD_ISO_ADR (DD_NISO_ADR + DD_NISO_SZ) /* Iso DMA Descr. Address */ |
|||
#define DD_SZ (128 + DD_NISO_SZ + DD_ISO_SZ) /* Descr. Size */ |
|||
|
|||
/* DMA Buffer Memory Definitions */ |
|||
#define DMA_BUF_ADR (USB_RAM_ADR + DD_SZ) /* DMA Buffer Start Address */ |
|||
#define DMA_BUF_SZ (USB_RAM_SZ - DD_SZ) /* DMA Buffer Size */ |
|||
|
|||
/* USB Error Codes */ |
|||
#define USB_ERR_PID 0x0001 /* PID Error */ |
|||
#define USB_ERR_UEPKT 0x0002 /* Unexpected Packet */ |
|||
#define USB_ERR_DCRC 0x0004 /* Data CRC Error */ |
|||
#define USB_ERR_TIMOUT 0x0008 /* Bus Time-out Error */ |
|||
#define USB_ERR_EOP 0x0010 /* End of Packet Error */ |
|||
#define USB_ERR_B_OVRN 0x0020 /* Buffer Overrun */ |
|||
#define USB_ERR_BTSTF 0x0040 /* Bit Stuff Error */ |
|||
#define USB_ERR_TGL 0x0080 /* Toggle Bit Error */ |
|||
|
|||
/* USB DMA Status Codes */ |
|||
#define USB_DMA_INVALID 0x0000 /* DMA Invalid - Not Configured */ |
|||
#define USB_DMA_IDLE 0x0001 /* DMA Idle - Waiting for Trigger */ |
|||
#define USB_DMA_BUSY 0x0002 /* DMA Busy - Transfer in progress */ |
|||
#define USB_DMA_DONE 0x0003 /* DMA Transfer Done (no Errors)*/ |
|||
#define USB_DMA_OVER_RUN 0x0004 /* Data Over Run */ |
|||
#define USB_DMA_UNDER_RUN 0x0005 /* Data Under Run (Short Packet) */ |
|||
#define USB_DMA_ERROR 0x0006 /* Error */ |
|||
#define USB_DMA_UNKNOWN 0xFFFF /* Unknown State */ |
|||
|
|||
/* USB DMA Descriptor */ |
|||
typedef struct _USB_DMA_DESCRIPTOR { |
|||
uint32_t BufAdr; /* DMA Buffer Address */ |
|||
uint16_t BufLen; /* DMA Buffer Length */ |
|||
uint16_t MaxSize; /* Maximum Packet Size */ |
|||
uint32_t InfoAdr; /* Packet Info Memory Address */ |
|||
union { /* DMA Configuration */ |
|||
struct { |
|||
uint32_t Link : 1; /* Link to existing Descriptors */ |
|||
uint32_t IsoEP : 1; /* Isonchronous Endpoint */ |
|||
uint32_t ATLE : 1; /* ATLE (Auto Transfer Length Extract) */ |
|||
uint32_t Rsrvd : 5; /* Reserved */ |
|||
uint32_t LenPos : 8; /* Length Position (ATLE) */ |
|||
} Type; |
|||
uint32_t Val; |
|||
} Cfg; |
|||
} USB_DMA_DESCRIPTOR; |
|||
|
|||
extern "C" { |
|||
/* USB Hardware Functions */ |
|||
extern void USB_Init (void); |
|||
extern void USB_Connect (uint32_t con); |
|||
extern void USB_Reset (void); |
|||
extern void USB_Suspend (void); |
|||
extern void USB_Resume (void); |
|||
extern void USB_WakeUp (void); |
|||
extern void USB_WakeUpCfg (uint32_t cfg); |
|||
extern void USB_SetAddress (uint32_t adr); |
|||
extern void USB_Configure (uint32_t cfg); |
|||
extern void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD); |
|||
extern void USB_DirCtrlEP (uint32_t dir); |
|||
extern void USB_EnableEP (uint32_t EPNum); |
|||
extern void USB_DisableEP (uint32_t EPNum); |
|||
extern void USB_ResetEP (uint32_t EPNum); |
|||
extern void USB_SetStallEP (uint32_t EPNum); |
|||
extern void USB_ClrStallEP (uint32_t EPNum); |
|||
extern void USB_ClearEPBuf (uint32_t EPNum); |
|||
extern uint32_t USB_ReadEP (uint32_t EPNum, uint8_t *pData); |
|||
extern uint32_t USB_WriteEP (uint32_t EPNum, uint8_t *pData, uint32_t cnt); |
|||
extern uint32_t USB_DMA_Setup (uint32_t EPNum, USB_DMA_DESCRIPTOR *pDD); |
|||
extern void USB_DMA_Enable (uint32_t EPNum); |
|||
extern void USB_DMA_Disable(uint32_t EPNum); |
|||
extern uint32_t USB_DMA_Status (uint32_t EPNum); |
|||
extern uint32_t USB_DMA_BufAdr (uint32_t EPNum); |
|||
extern uint32_t USB_DMA_BufCnt (uint32_t EPNum); |
|||
extern uint32_t USB_GetFrame (void); |
|||
extern void USB_IRQHandler (void); |
|||
} |
|||
|
|||
#endif /* __USBHW_H__ */ |
@ -0,0 +1,130 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: usbreg.h |
|||
* Purpose: USB Hardware Layer Definitions for NXP LPC Family MCUs |
|||
* Version: V1.20 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC family microcontroller devices only. Nothing |
|||
* else gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
#ifndef __USBREG_H |
|||
#define __USBREG_H |
|||
|
|||
/* Device Interrupt Bit Definitions */ |
|||
#define FRAME_INT 0x00000001 |
|||
#define EP_FAST_INT 0x00000002 |
|||
#define EP_SLOW_INT 0x00000004 |
|||
#define DEV_STAT_INT 0x00000008 |
|||
#define CCEMTY_INT 0x00000010 |
|||
#define CDFULL_INT 0x00000020 |
|||
#define RxENDPKT_INT 0x00000040 |
|||
#define TxENDPKT_INT 0x00000080 |
|||
#define EP_RLZED_INT 0x00000100 |
|||
#define ERR_INT 0x00000200 |
|||
|
|||
/* Rx & Tx Packet Length Definitions */ |
|||
#define PKT_LNGTH_MASK 0x000003FF |
|||
#define PKT_DV 0x00000400 |
|||
#define PKT_RDY 0x00000800 |
|||
|
|||
/* USB Control Definitions */ |
|||
#define CTRL_RD_EN 0x00000001 |
|||
#define CTRL_WR_EN 0x00000002 |
|||
|
|||
/* Command Codes */ |
|||
#define CMD_SET_ADDR 0x00D00500 |
|||
#define CMD_CFG_DEV 0x00D80500 |
|||
#define CMD_SET_MODE 0x00F30500 |
|||
#define CMD_RD_FRAME 0x00F50500 |
|||
#define DAT_RD_FRAME 0x00F50200 |
|||
#define CMD_RD_TEST 0x00FD0500 |
|||
#define DAT_RD_TEST 0x00FD0200 |
|||
#define CMD_SET_DEV_STAT 0x00FE0500 |
|||
#define CMD_GET_DEV_STAT 0x00FE0500 |
|||
#define DAT_GET_DEV_STAT 0x00FE0200 |
|||
#define CMD_GET_ERR_CODE 0x00FF0500 |
|||
#define DAT_GET_ERR_CODE 0x00FF0200 |
|||
#define CMD_RD_ERR_STAT 0x00FB0500 |
|||
#define DAT_RD_ERR_STAT 0x00FB0200 |
|||
#define DAT_WR_BYTE(x) (0x00000100 | ((x) << 16)) |
|||
#define CMD_SEL_EP(x) (0x00000500 | ((x) << 16)) |
|||
#define DAT_SEL_EP(x) (0x00000200 | ((x) << 16)) |
|||
#define CMD_SEL_EP_CLRI(x) (0x00400500 | ((x) << 16)) |
|||
#define DAT_SEL_EP_CLRI(x) (0x00400200 | ((x) << 16)) |
|||
#define CMD_SET_EP_STAT(x) (0x00400500 | ((x) << 16)) |
|||
#define CMD_CLR_BUF 0x00F20500 |
|||
#define DAT_CLR_BUF 0x00F20200 |
|||
#define CMD_VALID_BUF 0x00FA0500 |
|||
|
|||
/* Device Address Register Definitions */ |
|||
#define DEV_ADDR_MASK 0x7F |
|||
#define DEV_EN 0x80 |
|||
|
|||
/* Device Configure Register Definitions */ |
|||
#define CONF_DVICE 0x01 |
|||
|
|||
/* Device Mode Register Definitions */ |
|||
#define AP_CLK 0x01 |
|||
#define INAK_CI 0x02 |
|||
#define INAK_CO 0x04 |
|||
#define INAK_II 0x08 |
|||
#define INAK_IO 0x10 |
|||
#define INAK_BI 0x20 |
|||
#define INAK_BO 0x40 |
|||
|
|||
/* Device Status Register Definitions */ |
|||
#define DEV_CON 0x01 |
|||
#define DEV_CON_CH 0x02 |
|||
#define DEV_SUS 0x04 |
|||
#define DEV_SUS_CH 0x08 |
|||
#define DEV_RST 0x10 |
|||
|
|||
/* Error Code Register Definitions */ |
|||
#define ERR_EC_MASK 0x0F |
|||
#define ERR_EA 0x10 |
|||
|
|||
/* Error Status Register Definitions */ |
|||
#define ERR_PID 0x01 |
|||
#define ERR_UEPKT 0x02 |
|||
#define ERR_DCRC 0x04 |
|||
#define ERR_TIMOUT 0x08 |
|||
#define ERR_EOP 0x10 |
|||
#define ERR_B_OVRN 0x20 |
|||
#define ERR_BTSTF 0x40 |
|||
#define ERR_TGL 0x80 |
|||
|
|||
/* Endpoint Select Register Definitions */ |
|||
#define EP_SEL_F 0x01 |
|||
#define EP_SEL_ST 0x02 |
|||
#define EP_SEL_STP 0x04 |
|||
#define EP_SEL_PO 0x08 |
|||
#define EP_SEL_EPN 0x10 |
|||
#define EP_SEL_B_1_FULL 0x20 |
|||
#define EP_SEL_B_2_FULL 0x40 |
|||
|
|||
/* Endpoint Status Register Definitions */ |
|||
#define EP_STAT_ST 0x01 |
|||
#define EP_STAT_DA 0x20 |
|||
#define EP_STAT_RF_MO 0x40 |
|||
#define EP_STAT_CND_ST 0x80 |
|||
|
|||
/* Clear Buffer Register Definitions */ |
|||
#define CLR_BUF_PO 0x01 |
|||
|
|||
|
|||
/* DMA Interrupt Bit Definitions */ |
|||
#define EOT_INT 0x01 |
|||
#define NDD_REQ_INT 0x02 |
|||
#define SYS_ERR_INT 0x04 |
|||
|
|||
|
|||
#endif /* __USBREG_H */ |
@ -0,0 +1,353 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: usbuser.c |
|||
* Purpose: USB Custom User Module |
|||
* Version: V1.20 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC family microcontroller devices only. Nothing |
|||
* else gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
extern "C" { |
|||
#include "lpc_types.h" |
|||
#include <debug_frmwrk.h> |
|||
} |
|||
|
|||
#include "usb.h" |
|||
#include "usbcfg.h" |
|||
#include "usbhw.h" |
|||
#include "usbcore.h" |
|||
#include "usbuser.h" |
|||
#include "cdcuser.h" |
|||
#include "mscuser.h" |
|||
|
|||
|
|||
/*
|
|||
* USB Power Event Callback |
|||
* Called automatically on USB Power Event |
|||
* Parameter: power: On(TRUE)/Off(FALSE) |
|||
*/ |
|||
|
|||
#if USB_POWER_EVENT |
|||
void USB_Power_Event (uint32_t power) { |
|||
} |
|||
#endif |
|||
|
|||
|
|||
/*
|
|||
* USB Reset Event Callback |
|||
* Called automatically on USB Reset Event |
|||
*/ |
|||
|
|||
#if USB_RESET_EVENT |
|||
void USB_Reset_Event (void) { |
|||
USB_ResetCore(); |
|||
} |
|||
#endif |
|||
|
|||
|
|||
/*
|
|||
* USB Suspend Event Callback |
|||
* Called automatically on USB Suspend Event |
|||
*/ |
|||
|
|||
#if USB_SUSPEND_EVENT |
|||
void USB_Suspend_Event (void) { |
|||
} |
|||
#endif |
|||
|
|||
|
|||
/*
|
|||
* USB Resume Event Callback |
|||
* Called automatically on USB Resume Event |
|||
*/ |
|||
|
|||
#if USB_RESUME_EVENT |
|||
void USB_Resume_Event (void) { |
|||
} |
|||
#endif |
|||
|
|||
|
|||
/*
|
|||
* USB Remote Wakeup Event Callback |
|||
* Called automatically on USB Remote Wakeup Event |
|||
*/ |
|||
|
|||
#if USB_WAKEUP_EVENT |
|||
void USB_WakeUp_Event (void) { |
|||
} |
|||
#endif |
|||
|
|||
|
|||
/*
|
|||
* USB Start of Frame Event Callback |
|||
* Called automatically on USB Start of Frame Event |
|||
*/ |
|||
|
|||
#if USB_SOF_EVENT |
|||
void USB_SOF_Event (void) { |
|||
} |
|||
#endif |
|||
|
|||
|
|||
/*
|
|||
* USB Error Event Callback |
|||
* Called automatically on USB Error Event |
|||
* Parameter: error: Error Code |
|||
*/ |
|||
|
|||
#if USB_ERROR_EVENT |
|||
void USB_Error_Event (uint32_t error) { |
|||
} |
|||
#endif |
|||
|
|||
|
|||
/*
|
|||
* USB Set Configuration Event Callback |
|||
* Called automatically on USB Set Configuration Request |
|||
*/ |
|||
|
|||
#if USB_CONFIGURE_EVENT |
|||
void USB_Configure_Event (void) { |
|||
|
|||
if (USB_Configuration) { /* Check if USB is configured */ |
|||
/* add your code here */ |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
|
|||
/*
|
|||
* USB Set Interface Event Callback |
|||
* Called automatically on USB Set Interface Request |
|||
*/ |
|||
|
|||
#if USB_INTERFACE_EVENT |
|||
void USB_Interface_Event (void) { |
|||
} |
|||
#endif |
|||
|
|||
|
|||
/*
|
|||
* USB Set/Clear Feature Event Callback |
|||
* Called automatically on USB Set/Clear Feature Request |
|||
*/ |
|||
|
|||
#if USB_FEATURE_EVENT |
|||
void USB_Feature_Event (void) { |
|||
} |
|||
#endif |
|||
|
|||
|
|||
#define P_EP(n) ((USB_EP_EVENT & (1 << (n))) ? USB_EndPoint##n : nullptr) |
|||
|
|||
/* USB Endpoint Events Callback Pointers */ |
|||
void (* const USB_P_EP[16]) (uint32_t event) = { |
|||
P_EP(0), |
|||
P_EP(1), |
|||
P_EP(2), |
|||
P_EP(3), |
|||
P_EP(4), |
|||
P_EP(5), |
|||
P_EP(6), |
|||
P_EP(7), |
|||
P_EP(8), |
|||
P_EP(9), |
|||
P_EP(10), |
|||
P_EP(11), |
|||
P_EP(12), |
|||
P_EP(13), |
|||
P_EP(14), |
|||
P_EP(15), |
|||
}; |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 1 Event Callback |
|||
* Called automatically on USB Endpoint 1 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint1 (uint32_t event) { |
|||
uint16_t temp; |
|||
static uint16_t serialState; |
|||
|
|||
switch (event) { |
|||
case USB_EVT_IN: |
|||
temp = CDC_GetSerialState(); |
|||
if (serialState != temp) { |
|||
serialState = temp; |
|||
CDC_NotificationIn(); /* send SERIAL_STATE notification */ |
|||
} |
|||
break; |
|||
default: |
|||
_DBG("Unhandled EP1 event: "); |
|||
_DBH(event); |
|||
_DBG("\n"); |
|||
} |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 2 Event Callback |
|||
* Called automatically on USB Endpoint 2 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint2 (uint32_t event) { |
|||
|
|||
switch (event) { |
|||
case USB_EVT_OUT: |
|||
CDC_BulkOut (); /* data received from Host */ |
|||
break; |
|||
case USB_EVT_IN: |
|||
CDC_BulkIn (); /* data expected from Host */ |
|||
break; |
|||
} |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 3 Event Callback |
|||
* Called automatically on USB Endpoint 3 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint3 (uint32_t event) { |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 4 Event Callback |
|||
* Called automatically on USB Endpoint 4 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint4 (uint32_t event) { |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 5 Event Callback |
|||
* Called automatically on USB Endpoint 5 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint5 (uint32_t event) { |
|||
switch (event) { |
|||
case USB_EVT_OUT: |
|||
MSC_BulkOut(); |
|||
break; |
|||
case USB_EVT_IN: |
|||
MSC_BulkIn(); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 6 Event Callback |
|||
* Called automatically on USB Endpoint 6 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint6 (uint32_t event) { |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 7 Event Callback |
|||
* Called automatically on USB Endpoint 7 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint7 (uint32_t event) { |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 8 Event Callback |
|||
* Called automatically on USB Endpoint 8 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint8 (uint32_t event) { |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 9 Event Callback |
|||
* Called automatically on USB Endpoint 9 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint9 (uint32_t event) { |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 10 Event Callback |
|||
* Called automatically on USB Endpoint 10 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint10 (uint32_t event) { |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 11 Event Callback |
|||
* Called automatically on USB Endpoint 11 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint11 (uint32_t event) { |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 12 Event Callback |
|||
* Called automatically on USB Endpoint 12 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint12 (uint32_t event) { |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 13 Event Callback |
|||
* Called automatically on USB Endpoint 13 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint13 (uint32_t event) { |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 14 Event Callback |
|||
* Called automatically on USB Endpoint 14 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint14 (uint32_t event) { |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* USB Endpoint 15 Event Callback |
|||
* Called automatically on USB Endpoint 15 Event |
|||
* Parameter: event |
|||
*/ |
|||
|
|||
void USB_EndPoint15 (uint32_t event) { |
|||
} |
@ -0,0 +1,74 @@ |
|||
/*----------------------------------------------------------------------------
|
|||
* U S B - K e r n e l |
|||
*---------------------------------------------------------------------------- |
|||
* Name: usbuser.h |
|||
* Purpose: USB Custom User Definitions |
|||
* Version: V1.20 |
|||
*---------------------------------------------------------------------------- |
|||
* This software is supplied "AS IS" without any warranties, express, |
|||
* implied or statutory, including but not limited to the implied |
|||
* warranties of fitness for purpose, satisfactory quality and |
|||
* noninfringement. Keil extends you a royalty-free right to reproduce |
|||
* and distribute executable files created using this software for use |
|||
* on NXP Semiconductors LPC family microcontroller devices only. Nothing |
|||
* else gives you the right to use this software. |
|||
* |
|||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved. |
|||
*---------------------------------------------------------------------------*/ |
|||
|
|||
#ifndef __USBUSER_H__ |
|||
#define __USBUSER_H__ |
|||
|
|||
|
|||
/* USB Device Events Callback Functions */ |
|||
extern void USB_Power_Event (uint32_t power); |
|||
extern void USB_Reset_Event (void); |
|||
extern void USB_Suspend_Event (void); |
|||
extern void USB_Resume_Event (void); |
|||
extern void USB_WakeUp_Event (void); |
|||
extern void USB_SOF_Event (void); |
|||
extern void USB_Error_Event (uint32_t error); |
|||
|
|||
/* USB Endpoint Callback Events */ |
|||
#define USB_EVT_SETUP 1 /* Setup Packet */ |
|||
#define USB_EVT_OUT 2 /* OUT Packet */ |
|||
#define USB_EVT_IN 3 /* IN Packet */ |
|||
#define USB_EVT_OUT_NAK 4 /* OUT Packet - Not Acknowledged */ |
|||
#define USB_EVT_IN_NAK 5 /* IN Packet - Not Acknowledged */ |
|||
#define USB_EVT_OUT_STALL 6 /* OUT Packet - Stalled */ |
|||
#define USB_EVT_IN_STALL 7 /* IN Packet - Stalled */ |
|||
#define USB_EVT_OUT_DMA_EOT 8 /* DMA OUT EP - End of Transfer */ |
|||
#define USB_EVT_IN_DMA_EOT 9 /* DMA IN EP - End of Transfer */ |
|||
#define USB_EVT_OUT_DMA_NDR 10 /* DMA OUT EP - New Descriptor Request */ |
|||
#define USB_EVT_IN_DMA_NDR 11 /* DMA IN EP - New Descriptor Request */ |
|||
#define USB_EVT_OUT_DMA_ERR 12 /* DMA OUT EP - Error */ |
|||
#define USB_EVT_IN_DMA_ERR 13 /* DMA IN EP - Error */ |
|||
|
|||
/* USB Endpoint Events Callback Pointers */ |
|||
extern void (* const USB_P_EP[16])(uint32_t event); |
|||
|
|||
/* USB Endpoint Events Callback Functions */ |
|||
extern void USB_EndPoint0 (uint32_t event); |
|||
extern void USB_EndPoint1 (uint32_t event); |
|||
extern void USB_EndPoint2 (uint32_t event); |
|||
extern void USB_EndPoint3 (uint32_t event); |
|||
extern void USB_EndPoint4 (uint32_t event); |
|||
extern void USB_EndPoint5 (uint32_t event); |
|||
extern void USB_EndPoint6 (uint32_t event); |
|||
extern void USB_EndPoint7 (uint32_t event); |
|||
extern void USB_EndPoint8 (uint32_t event); |
|||
extern void USB_EndPoint9 (uint32_t event); |
|||
extern void USB_EndPoint10 (uint32_t event); |
|||
extern void USB_EndPoint11 (uint32_t event); |
|||
extern void USB_EndPoint12 (uint32_t event); |
|||
extern void USB_EndPoint13 (uint32_t event); |
|||
extern void USB_EndPoint14 (uint32_t event); |
|||
extern void USB_EndPoint15 (uint32_t event); |
|||
|
|||
/* USB Core Events Callback Functions */ |
|||
extern void USB_Configure_Event (void); |
|||
extern void USB_Interface_Event (void); |
|||
extern void USB_Feature_Event (void); |
|||
|
|||
|
|||
#endif /* __USBUSER_H__ */ |
Loading…
Reference in new issue