mirror of
https://github.com/brmlab/edubrm.git
synced 2025-06-11 14:14:00 +02:00
build without eclipse :)
This commit is contained in:
parent
c3ff2207cd
commit
8b871d5d47
50 changed files with 143 additions and 2514 deletions
166
firmware/src/DiskImg.c
Normal file
166
firmware/src/DiskImg.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
/* Disk Image */
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
const unsigned char DiskImage[MSC_ImageSize] = {
|
||||
0xEB,0x3C,0x90,0x4D,0x53,0x44,0x4F,0x53,0x35,0x2E,0x30,0x00,0x02,0x01,0x01,0x00,
|
||||
0x01,0x10,0x00,0x20,0x00,0xF8,0x02,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x74,0x19,0x02,0x27,0x4C,0x50,0x43,0x32,0x33,
|
||||
0x36,0x38,0x20,0x55,0x53,0x42,0x46,0x41,0x54,0x31,0x32,0x20,0x20,0x20,0x33,0xC9,
|
||||
0x8E,0xD1,0xBC,0xF0,0x7B,0x8E,0xD9,0xB8,0x00,0x20,0x8E,0xC0,0xFC,0xBD,0x00,0x7C,
|
||||
0x38,0x4E,0x24,0x7D,0x24,0x8B,0xC1,0x99,0xE8,0x3C,0x01,0x72,0x1C,0x83,0xEB,0x3A,
|
||||
0x66,0xA1,0x1C,0x7C,0x26,0x66,0x3B,0x07,0x26,0x8A,0x57,0xFC,0x75,0x06,0x80,0xCA,
|
||||
0x02,0x88,0x56,0x02,0x80,0xC3,0x10,0x73,0xEB,0x33,0xC9,0x8A,0x46,0x10,0x98,0xF7,
|
||||
0x66,0x16,0x03,0x46,0x1C,0x13,0x56,0x1E,0x03,0x46,0x0E,0x13,0xD1,0x8B,0x76,0x11,
|
||||
0x60,0x89,0x46,0xFC,0x89,0x56,0xFE,0xB8,0x20,0x00,0xF7,0xE6,0x8B,0x5E,0x0B,0x03,
|
||||
0xC3,0x48,0xF7,0xF3,0x01,0x46,0xFC,0x11,0x4E,0xFE,0x61,0xBF,0x00,0x00,0xE8,0xE6,
|
||||
0x00,0x72,0x39,0x26,0x38,0x2D,0x74,0x17,0x60,0xB1,0x0B,0xBE,0xA1,0x7D,0xF3,0xA6,
|
||||
0x61,0x74,0x32,0x4E,0x74,0x09,0x83,0xC7,0x20,0x3B,0xFB,0x72,0xE6,0xEB,0xDC,0xA0,
|
||||
0xFB,0x7D,0xB4,0x7D,0x8B,0xF0,0xAC,0x98,0x40,0x74,0x0C,0x48,0x74,0x13,0xB4,0x0E,
|
||||
0xBB,0x07,0x00,0xCD,0x10,0xEB,0xEF,0xA0,0xFD,0x7D,0xEB,0xE6,0xA0,0xFC,0x7D,0xEB,
|
||||
0xE1,0xCD,0x16,0xCD,0x19,0x26,0x8B,0x55,0x1A,0x52,0xB0,0x01,0xBB,0x00,0x00,0xE8,
|
||||
0x3B,0x00,0x72,0xE8,0x5B,0x8A,0x56,0x24,0xBE,0x0B,0x7C,0x8B,0xFC,0xC7,0x46,0xF0,
|
||||
0x3D,0x7D,0xC7,0x46,0xF4,0x29,0x7D,0x8C,0xD9,0x89,0x4E,0xF2,0x89,0x4E,0xF6,0xC6,
|
||||
0x06,0x96,0x7D,0xCB,0xEA,0x03,0x00,0x00,0x20,0x0F,0xB6,0xC8,0x66,0x8B,0x46,0xF8,
|
||||
0x66,0x03,0x46,0x1C,0x66,0x8B,0xD0,0x66,0xC1,0xEA,0x10,0xEB,0x5E,0x0F,0xB6,0xC8,
|
||||
0x4A,0x4A,0x8A,0x46,0x0D,0x32,0xE4,0xF7,0xE2,0x03,0x46,0xFC,0x13,0x56,0xFE,0xEB,
|
||||
0x4A,0x52,0x50,0x06,0x53,0x6A,0x01,0x6A,0x10,0x91,0x8B,0x46,0x18,0x96,0x92,0x33,
|
||||
0xD2,0xF7,0xF6,0x91,0xF7,0xF6,0x42,0x87,0xCA,0xF7,0x76,0x1A,0x8A,0xF2,0x8A,0xE8,
|
||||
0xC0,0xCC,0x02,0x0A,0xCC,0xB8,0x01,0x02,0x80,0x7E,0x02,0x0E,0x75,0x04,0xB4,0x42,
|
||||
0x8B,0xF4,0x8A,0x56,0x24,0xCD,0x13,0x61,0x61,0x72,0x0B,0x40,0x75,0x01,0x42,0x03,
|
||||
0x5E,0x0B,0x49,0x75,0x06,0xF8,0xC3,0x41,0xBB,0x00,0x00,0x60,0x66,0x6A,0x00,0xEB,
|
||||
0xB0,0x4E,0x54,0x4C,0x44,0x52,0x20,0x20,0x20,0x20,0x20,0x20,0x0D,0x0A,0x52,0x65,
|
||||
0x6D,0x6F,0x76,0x65,0x20,0x64,0x69,0x73,0x6B,0x73,0x20,0x6F,0x72,0x20,0x6F,0x74,
|
||||
0x68,0x65,0x72,0x20,0x6D,0x65,0x64,0x69,0x61,0x2E,0xFF,0x0D,0x0A,0x44,0x69,0x73,
|
||||
0x6B,0x20,0x65,0x72,0x72,0x6F,0x72,0xFF,0x0D,0x0A,0x50,0x72,0x65,0x73,0x73,0x20,
|
||||
0x61,0x6E,0x79,0x20,0x6B,0x65,0x79,0x20,0x74,0x6F,0x20,0x72,0x65,0x73,0x74,0x61,
|
||||
0x72,0x74,0x0D,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0xCB,0xD8,0x55,0xAA,
|
||||
0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x4C,0x50,0x43,0x31,0x33,0x34,0x78,0x20,0x55,0x53,0x42,0x28,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x52,0x45,0x41,0x44,0x4D,0x45,0x20,0x20,0x54,0x58,0x54,0x21,0x00,0x00,0x00,0x00,
|
||||
0x21,0x00,0xBB,0x32,0x00,0x00,0xDC,0x83,0xBB,0x32,0x02,0x00,0x5D,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x61,0x20,0x55,0x53,0x42,0x20,0x4D,0x65,
|
||||
0x6D,0x6F,0x72,0x79,0x20,0x44,0x65,0x76,0x69,0x63,0x65,0x20,0x64,0x65,0x6D,0x6F,
|
||||
0x6E,0x73,0x74,0x72,0x61,0x74,0x69,0x6F,0x6E,0x20,0x66,0x6F,0x72,0x0D,0x0A,0x74,
|
||||
0x68,0x65,0x20,0x4E,0x58,0x50,0x20,0x20,0x4E,0x58,0x50,0x31,0x33,0x58,0x58,0x20,
|
||||
0x42,0x6F,0x61,0x72,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x4E,0x58,0x50,0x20,0x4C,
|
||||
0x50,0x43,0x31,0x33,0x34,0x33,0x2E,0x20,0x20,0x20,0x20,0x0D,0x0A,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
};
|
360
firmware/src/cdcuser.c
Normal file
360
firmware/src/cdcuser.c
Normal file
|
@ -0,0 +1,360 @@
|
|||
/*----------------------------------------------------------------------------
|
||||
* 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.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "type.h"
|
||||
|
||||
#include "usb.h"
|
||||
#include "usbhw.h"
|
||||
#include "usbcfg.h"
|
||||
#include "usbcore.h"
|
||||
#include "cdc.h"
|
||||
#include "cdcuser.h"
|
||||
#include "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 = {9600, 0, 0, 8};
|
||||
unsigned short CDC_SerialState = 0x0000;
|
||||
unsigned short CDC_DepInEmpty = 1; // Data IN EP is empty
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
We need a buffer for incomming data on USB port because USB receives
|
||||
much faster than UART transmits
|
||||
*---------------------------------------------------------------------------*/
|
||||
/* Buffer masks */
|
||||
#define CDC_BUF_SIZE (64) // Output buffer in bytes (power 2)
|
||||
// large enough for file transfer
|
||||
#define CDC_BUF_MASK (CDC_BUF_SIZE-1ul)
|
||||
|
||||
/* Buffer read / write macros */
|
||||
#define CDC_BUF_RESET(cdcBuf) (cdcBuf.rdIdx = cdcBuf.wrIdx = 0)
|
||||
#define CDC_BUF_WR(cdcBuf, dataIn) (cdcBuf.data[CDC_BUF_MASK & cdcBuf.wrIdx++] = (dataIn))
|
||||
#define CDC_BUF_RD(cdcBuf) (cdcBuf.data[CDC_BUF_MASK & cdcBuf.rdIdx++])
|
||||
#define CDC_BUF_EMPTY(cdcBuf) (cdcBuf.rdIdx == cdcBuf.wrIdx)
|
||||
#define CDC_BUF_FULL(cdcBuf) (cdcBuf.rdIdx == cdcBuf.wrIdx+1)
|
||||
#define CDC_BUF_COUNT(cdcBuf) (CDC_BUF_MASK & (cdcBuf.wrIdx - cdcBuf.rdIdx))
|
||||
|
||||
|
||||
// CDC output buffer
|
||||
typedef struct __CDC_BUF_T {
|
||||
unsigned char data[CDC_BUF_SIZE];
|
||||
unsigned int wrIdx;
|
||||
unsigned int rdIdx;
|
||||
} CDC_BUF_T;
|
||||
|
||||
CDC_BUF_T CDC_OutBuf; // buffer for all CDC Out data
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
read data from CDC_OutBuf
|
||||
*---------------------------------------------------------------------------*/
|
||||
int CDC_RdOutBuf (char *buffer, const int *length) {
|
||||
int bytesToRead, bytesRead;
|
||||
|
||||
/* Read *length bytes, block if *bytes are not avaialable */
|
||||
bytesToRead = *length;
|
||||
bytesToRead = (bytesToRead < (*length)) ? bytesToRead : (*length);
|
||||
bytesRead = bytesToRead;
|
||||
|
||||
|
||||
// ... add code to check for underrun
|
||||
|
||||
while (bytesToRead--) {
|
||||
*buffer++ = CDC_BUF_RD(CDC_OutBuf);
|
||||
}
|
||||
return (bytesRead);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
write data to CDC_OutBuf
|
||||
*---------------------------------------------------------------------------*/
|
||||
int CDC_WrOutBuf (const char *buffer, int *length) {
|
||||
int bytesToWrite, bytesWritten;
|
||||
|
||||
// Write *length bytes
|
||||
bytesToWrite = *length;
|
||||
bytesWritten = bytesToWrite;
|
||||
|
||||
|
||||
// ... add code to check for overwrite
|
||||
|
||||
while (bytesToWrite) {
|
||||
CDC_BUF_WR(CDC_OutBuf, *buffer++); // Copy Data to buffer
|
||||
bytesToWrite--;
|
||||
}
|
||||
|
||||
return (bytesWritten);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
check if character(s) are available at CDC_OutBuf
|
||||
*---------------------------------------------------------------------------*/
|
||||
int CDC_OutBufAvailChar (int *availChar) {
|
||||
|
||||
*availChar = CDC_BUF_COUNT(CDC_OutBuf);
|
||||
|
||||
return (0);
|
||||
}
|
||||
/* end Buffer handling */
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
CDC Initialisation
|
||||
Initializes the data structures and serial port
|
||||
Parameters: None
|
||||
Return Value: None
|
||||
*---------------------------------------------------------------------------*/
|
||||
void CDC_Init (void) {
|
||||
|
||||
ser_OpenPort ();
|
||||
ser_InitPort (CDC_LineCoding.dwDTERate,
|
||||
CDC_LineCoding.bDataBits,
|
||||
CDC_LineCoding.bParityType,
|
||||
CDC_LineCoding.bCharFormat);
|
||||
|
||||
CDC_DepInEmpty = 1;
|
||||
CDC_SerialState = CDC_GetSerialState();
|
||||
|
||||
CDC_BUF_RESET(CDC_OutBuf);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
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];
|
||||
|
||||
ser_ClosePort();
|
||||
ser_OpenPort ();
|
||||
ser_InitPort (CDC_LineCoding.dwDTERate,
|
||||
CDC_LineCoding.bDataBits,
|
||||
CDC_LineCoding.bParityType,
|
||||
CDC_LineCoding.bCharFormat);
|
||||
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) {
|
||||
|
||||
/* ... add code to handle request */
|
||||
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) {
|
||||
int numBytesRead, numBytesAvail;
|
||||
|
||||
ser_AvailChar (&numBytesAvail);
|
||||
|
||||
// ... add code to check for overwrite
|
||||
|
||||
numBytesRead = ser_Read ((char *)&BulkBufIn[0], &numBytesAvail);
|
||||
|
||||
// send over USB
|
||||
if (numBytesRead > 0) {
|
||||
USB_WriteEP (CDC_DEP_IN, &BulkBufIn[0], numBytesRead);
|
||||
}
|
||||
else {
|
||||
CDC_DepInEmpty = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
CDC_BulkOut call on DataOut Request
|
||||
Parameters: none
|
||||
Return Value: none
|
||||
*---------------------------------------------------------------------------*/
|
||||
void CDC_BulkOut(void) {
|
||||
int numBytesRead;
|
||||
|
||||
// get data from USB into intermediate buffer
|
||||
numBytesRead = USB_ReadEP(CDC_DEP_OUT, &BulkBufOut[0]);
|
||||
|
||||
// ... add code to check for overwrite
|
||||
|
||||
// store data in a buffer to transmit it over serial interface
|
||||
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) {
|
||||
unsigned short temp;
|
||||
|
||||
CDC_SerialState = 0;
|
||||
ser_LineState (&temp);
|
||||
|
||||
if (temp & 0x8000) CDC_SerialState |= CDC_SERIAL_STATE_RX_CARRIER;
|
||||
if (temp & 0x2000) CDC_SerialState |= CDC_SERIAL_STATE_TX_CARRIER;
|
||||
if (temp & 0x0010) CDC_SerialState |= CDC_SERIAL_STATE_BREAK;
|
||||
if (temp & 0x4000) CDC_SerialState |= CDC_SERIAL_STATE_RING;
|
||||
if (temp & 0x0008) CDC_SerialState |= CDC_SERIAL_STATE_FRAMING;
|
||||
if (temp & 0x0004) CDC_SerialState |= CDC_SERIAL_STATE_PARITY;
|
||||
if (temp & 0x0002) CDC_SerialState |= CDC_SERIAL_STATE_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
|
||||
}
|
60
firmware/src/clkconfig.c
Normal file
60
firmware/src/clkconfig.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/******************************************************************************
|
||||
* clkconfig.c: clock configuration C file for NXP LPC13xx Family
|
||||
* Microprocessors
|
||||
*
|
||||
* Copyright(C) 2009, NXP Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* History
|
||||
* 2009.08.20 ver 1.00 Preliminary version, first Release
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "LPC13xx.h"
|
||||
#include "clkconfig.h"
|
||||
|
||||
/*****************************************************************************
|
||||
** Function name: WDT_CLK_Setup
|
||||
**
|
||||
** Descriptions: Configure WDT clock.
|
||||
** parameters: clock source: irc_osc(0), main_clk(1), wdt_osc(2).
|
||||
**
|
||||
** Returned value: None
|
||||
**
|
||||
*****************************************************************************/
|
||||
void WDT_CLK_Setup ( uint32_t clksrc )
|
||||
{
|
||||
/* Watchdog configuration. */
|
||||
/* Freq = 0.5Mhz, div_sel is 0, divided by 2. WDT_OSC should be 250khz */
|
||||
LPC_SYSCON->WDTOSCCTRL = (0x1<<5)|0x00;
|
||||
LPC_SYSCON->WDTCLKSEL = clksrc; /* Select clock source */
|
||||
LPC_SYSCON->WDTCLKUEN = 0x01; /* Update clock */
|
||||
LPC_SYSCON->WDTCLKUEN = 0x00; /* Toggle update register once */
|
||||
LPC_SYSCON->WDTCLKUEN = 0x01;
|
||||
while ( !(LPC_SYSCON->WDTCLKUEN & 0x01) ); /* Wait until updated */
|
||||
LPC_SYSCON->WDTCLKDIV = 1; /* Divided by 1 */
|
||||
LPC_SYSCON->PDRUNCFG &= ~(0x1<<6); /* Let WDT clock run */
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Function name: CLKOUT_Setup
|
||||
**
|
||||
** Descriptions: Configure CLKOUT for reference clock check.
|
||||
** parameters: clock source: irc_osc(0), sys_osc(1), wdt_osc(2),
|
||||
** main_clk(3).
|
||||
**
|
||||
** Returned value: None
|
||||
**
|
||||
*****************************************************************************/
|
||||
void CLKOUT_Setup ( uint32_t clksrc )
|
||||
{
|
||||
/* debug PLL after configuration. */
|
||||
LPC_SYSCON->CLKOUTCLKSEL = clksrc; /* Select Main clock */
|
||||
LPC_SYSCON->CLKOUTUEN = 0x01; /* Update clock */
|
||||
LPC_SYSCON->CLKOUTUEN = 0x00; /* Toggle update register once */
|
||||
LPC_SYSCON->CLKOUTUEN = 0x01;
|
||||
while ( !(LPC_SYSCON->CLKOUTUEN & 0x01) ); /* Wait until updated */
|
||||
LPC_SYSCON->CLKOUTDIV = 1; /* Divided by 1 */
|
||||
return;
|
||||
}
|
||||
|
784
firmware/src/core_cm3.c
Normal file
784
firmware/src/core_cm3.c
Normal file
|
@ -0,0 +1,784 @@
|
|||
/**************************************************************************//**
|
||||
* @file core_cm3.c
|
||||
* @brief CMSIS Cortex-M3 Core Peripheral Access Layer Source File
|
||||
* @version V1.30
|
||||
* @date 30. October 2009
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2009 ARM Limited. All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* ARM Limited (ARM) is supplying this software for use with Cortex-M
|
||||
* processor based microcontrollers. This file can be freely distributed
|
||||
* within development tools that are supporting such ARM based processors.
|
||||
*
|
||||
* @par
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
|
||||
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
|
||||
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
|
||||
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* define compiler specific symbols */
|
||||
#if defined ( __CC_ARM )
|
||||
#define __ASM __asm /*!< asm keyword for ARM Compiler */
|
||||
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
#define __ASM __asm /*!< asm keyword for IAR Compiler */
|
||||
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */
|
||||
|
||||
#elif defined ( __GNUC__ )
|
||||
#define __ASM __asm /*!< asm keyword for GNU Compiler */
|
||||
#define __INLINE inline /*!< inline keyword for GNU Compiler */
|
||||
|
||||
#elif defined ( __TASKING__ )
|
||||
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
|
||||
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* ################### Compiler specific Intrinsics ########################### */
|
||||
|
||||
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
|
||||
/* ARM armcc specific functions */
|
||||
|
||||
/**
|
||||
* @brief Return the Process Stack Pointer
|
||||
*
|
||||
* @return ProcessStackPointer
|
||||
*
|
||||
* Return the actual process stack pointer
|
||||
*/
|
||||
__ASM uint32_t __get_PSP(void)
|
||||
{
|
||||
mrs r0, psp
|
||||
bx lr
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Process Stack Pointer
|
||||
*
|
||||
* @param topOfProcStack Process Stack Pointer
|
||||
*
|
||||
* Assign the value ProcessStackPointer to the MSP
|
||||
* (process stack pointer) Cortex processor register
|
||||
*/
|
||||
__ASM void __set_PSP(uint32_t topOfProcStack)
|
||||
{
|
||||
msr psp, r0
|
||||
bx lr
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Main Stack Pointer
|
||||
*
|
||||
* @return Main Stack Pointer
|
||||
*
|
||||
* Return the current value of the MSP (main stack pointer)
|
||||
* Cortex processor register
|
||||
*/
|
||||
__ASM uint32_t __get_MSP(void)
|
||||
{
|
||||
mrs r0, msp
|
||||
bx lr
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Main Stack Pointer
|
||||
*
|
||||
* @param topOfMainStack Main Stack Pointer
|
||||
*
|
||||
* Assign the value mainStackPointer to the MSP
|
||||
* (main stack pointer) Cortex processor register
|
||||
*/
|
||||
__ASM void __set_MSP(uint32_t mainStackPointer)
|
||||
{
|
||||
msr msp, r0
|
||||
bx lr
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reverse byte order in unsigned short value
|
||||
*
|
||||
* @param value value to reverse
|
||||
* @return reversed value
|
||||
*
|
||||
* Reverse byte order in unsigned short value
|
||||
*/
|
||||
__ASM uint32_t __REV16(uint16_t value)
|
||||
{
|
||||
rev16 r0, r0
|
||||
bx lr
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reverse byte order in signed short value with sign extension to integer
|
||||
*
|
||||
* @param value value to reverse
|
||||
* @return reversed value
|
||||
*
|
||||
* Reverse byte order in signed short value with sign extension to integer
|
||||
*/
|
||||
__ASM int32_t __REVSH(int16_t value)
|
||||
{
|
||||
revsh r0, r0
|
||||
bx lr
|
||||
}
|
||||
|
||||
|
||||
#if (__ARMCC_VERSION < 400000)
|
||||
|
||||
/**
|
||||
* @brief Remove the exclusive lock created by ldrex
|
||||
*
|
||||
* Removes the exclusive lock which is created by ldrex.
|
||||
*/
|
||||
__ASM void __CLREX(void)
|
||||
{
|
||||
clrex
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Base Priority value
|
||||
*
|
||||
* @return BasePriority
|
||||
*
|
||||
* Return the content of the base priority register
|
||||
*/
|
||||
__ASM uint32_t __get_BASEPRI(void)
|
||||
{
|
||||
mrs r0, basepri
|
||||
bx lr
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Base Priority value
|
||||
*
|
||||
* @param basePri BasePriority
|
||||
*
|
||||
* Set the base priority register
|
||||
*/
|
||||
__ASM void __set_BASEPRI(uint32_t basePri)
|
||||
{
|
||||
msr basepri, r0
|
||||
bx lr
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Priority Mask value
|
||||
*
|
||||
* @return PriMask
|
||||
*
|
||||
* Return state of the priority mask bit from the priority mask register
|
||||
*/
|
||||
__ASM uint32_t __get_PRIMASK(void)
|
||||
{
|
||||
mrs r0, primask
|
||||
bx lr
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Priority Mask value
|
||||
*
|
||||
* @param priMask PriMask
|
||||
*
|
||||
* Set the priority mask bit in the priority mask register
|
||||
*/
|
||||
__ASM void __set_PRIMASK(uint32_t priMask)
|
||||
{
|
||||
msr primask, r0
|
||||
bx lr
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Fault Mask value
|
||||
*
|
||||
* @return FaultMask
|
||||
*
|
||||
* Return the content of the fault mask register
|
||||
*/
|
||||
__ASM uint32_t __get_FAULTMASK(void)
|
||||
{
|
||||
mrs r0, faultmask
|
||||
bx lr
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Fault Mask value
|
||||
*
|
||||
* @param faultMask faultMask value
|
||||
*
|
||||
* Set the fault mask register
|
||||
*/
|
||||
__ASM void __set_FAULTMASK(uint32_t faultMask)
|
||||
{
|
||||
msr faultmask, r0
|
||||
bx lr
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Control Register value
|
||||
*
|
||||
* @return Control value
|
||||
*
|
||||
* Return the content of the control register
|
||||
*/
|
||||
__ASM uint32_t __get_CONTROL(void)
|
||||
{
|
||||
mrs r0, control
|
||||
bx lr
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Control Register value
|
||||
*
|
||||
* @param control Control value
|
||||
*
|
||||
* Set the control register
|
||||
*/
|
||||
__ASM void __set_CONTROL(uint32_t control)
|
||||
{
|
||||
msr control, r0
|
||||
bx lr
|
||||
}
|
||||
|
||||
#endif /* __ARMCC_VERSION */
|
||||
|
||||
|
||||
|
||||
#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/
|
||||
/* IAR iccarm specific functions */
|
||||
#pragma diag_suppress=Pe940
|
||||
|
||||
/**
|
||||
* @brief Return the Process Stack Pointer
|
||||
*
|
||||
* @return ProcessStackPointer
|
||||
*
|
||||
* Return the actual process stack pointer
|
||||
*/
|
||||
uint32_t __get_PSP(void)
|
||||
{
|
||||
__ASM("mrs r0, psp");
|
||||
__ASM("bx lr");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Process Stack Pointer
|
||||
*
|
||||
* @param topOfProcStack Process Stack Pointer
|
||||
*
|
||||
* Assign the value ProcessStackPointer to the MSP
|
||||
* (process stack pointer) Cortex processor register
|
||||
*/
|
||||
void __set_PSP(uint32_t topOfProcStack)
|
||||
{
|
||||
__ASM("msr psp, r0");
|
||||
__ASM("bx lr");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Main Stack Pointer
|
||||
*
|
||||
* @return Main Stack Pointer
|
||||
*
|
||||
* Return the current value of the MSP (main stack pointer)
|
||||
* Cortex processor register
|
||||
*/
|
||||
uint32_t __get_MSP(void)
|
||||
{
|
||||
__ASM("mrs r0, msp");
|
||||
__ASM("bx lr");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Main Stack Pointer
|
||||
*
|
||||
* @param topOfMainStack Main Stack Pointer
|
||||
*
|
||||
* Assign the value mainStackPointer to the MSP
|
||||
* (main stack pointer) Cortex processor register
|
||||
*/
|
||||
void __set_MSP(uint32_t topOfMainStack)
|
||||
{
|
||||
__ASM("msr msp, r0");
|
||||
__ASM("bx lr");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reverse byte order in unsigned short value
|
||||
*
|
||||
* @param value value to reverse
|
||||
* @return reversed value
|
||||
*
|
||||
* Reverse byte order in unsigned short value
|
||||
*/
|
||||
uint32_t __REV16(uint16_t value)
|
||||
{
|
||||
__ASM("rev16 r0, r0");
|
||||
__ASM("bx lr");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reverse bit order of value
|
||||
*
|
||||
* @param value value to reverse
|
||||
* @return reversed value
|
||||
*
|
||||
* Reverse bit order of value
|
||||
*/
|
||||
uint32_t __RBIT(uint32_t value)
|
||||
{
|
||||
__ASM("rbit r0, r0");
|
||||
__ASM("bx lr");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LDR Exclusive (8 bit)
|
||||
*
|
||||
* @param *addr address pointer
|
||||
* @return value of (*address)
|
||||
*
|
||||
* Exclusive LDR command for 8 bit values)
|
||||
*/
|
||||
uint8_t __LDREXB(uint8_t *addr)
|
||||
{
|
||||
__ASM("ldrexb r0, [r0]");
|
||||
__ASM("bx lr");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LDR Exclusive (16 bit)
|
||||
*
|
||||
* @param *addr address pointer
|
||||
* @return value of (*address)
|
||||
*
|
||||
* Exclusive LDR command for 16 bit values
|
||||
*/
|
||||
uint16_t __LDREXH(uint16_t *addr)
|
||||
{
|
||||
__ASM("ldrexh r0, [r0]");
|
||||
__ASM("bx lr");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LDR Exclusive (32 bit)
|
||||
*
|
||||
* @param *addr address pointer
|
||||
* @return value of (*address)
|
||||
*
|
||||
* Exclusive LDR command for 32 bit values
|
||||
*/
|
||||
uint32_t __LDREXW(uint32_t *addr)
|
||||
{
|
||||
__ASM("ldrex r0, [r0]");
|
||||
__ASM("bx lr");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief STR Exclusive (8 bit)
|
||||
*
|
||||
* @param value value to store
|
||||
* @param *addr address pointer
|
||||
* @return successful / failed
|
||||
*
|
||||
* Exclusive STR command for 8 bit values
|
||||
*/
|
||||
uint32_t __STREXB(uint8_t value, uint8_t *addr)
|
||||
{
|
||||
__ASM("strexb r0, r0, [r1]");
|
||||
__ASM("bx lr");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief STR Exclusive (16 bit)
|
||||
*
|
||||
* @param value value to store
|
||||
* @param *addr address pointer
|
||||
* @return successful / failed
|
||||
*
|
||||
* Exclusive STR command for 16 bit values
|
||||
*/
|
||||
uint32_t __STREXH(uint16_t value, uint16_t *addr)
|
||||
{
|
||||
__ASM("strexh r0, r0, [r1]");
|
||||
__ASM("bx lr");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief STR Exclusive (32 bit)
|
||||
*
|
||||
* @param value value to store
|
||||
* @param *addr address pointer
|
||||
* @return successful / failed
|
||||
*
|
||||
* Exclusive STR command for 32 bit values
|
||||
*/
|
||||
uint32_t __STREXW(uint32_t value, uint32_t *addr)
|
||||
{
|
||||
__ASM("strex r0, r0, [r1]");
|
||||
__ASM("bx lr");
|
||||
}
|
||||
|
||||
#pragma diag_default=Pe940
|
||||
|
||||
|
||||
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
|
||||
/* GNU gcc specific functions */
|
||||
|
||||
/**
|
||||
* @brief Return the Process Stack Pointer
|
||||
*
|
||||
* @return ProcessStackPointer
|
||||
*
|
||||
* Return the actual process stack pointer
|
||||
*/
|
||||
uint32_t __get_PSP(void) __attribute__( ( naked ) );
|
||||
uint32_t __get_PSP(void)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("MRS %0, psp\n\t"
|
||||
"MOV r0, %0 \n\t"
|
||||
"BX lr \n\t" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Process Stack Pointer
|
||||
*
|
||||
* @param topOfProcStack Process Stack Pointer
|
||||
*
|
||||
* Assign the value ProcessStackPointer to the MSP
|
||||
* (process stack pointer) Cortex processor register
|
||||
*/
|
||||
void __set_PSP(uint32_t topOfProcStack) __attribute__( ( naked ) );
|
||||
void __set_PSP(uint32_t topOfProcStack)
|
||||
{
|
||||
__ASM volatile ("MSR psp, %0\n\t"
|
||||
"BX lr \n\t" : : "r" (topOfProcStack) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Main Stack Pointer
|
||||
*
|
||||
* @return Main Stack Pointer
|
||||
*
|
||||
* Return the current value of the MSP (main stack pointer)
|
||||
* Cortex processor register
|
||||
*/
|
||||
uint32_t __get_MSP(void) __attribute__( ( naked ) );
|
||||
uint32_t __get_MSP(void)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("MRS %0, msp\n\t"
|
||||
"MOV r0, %0 \n\t"
|
||||
"BX lr \n\t" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Main Stack Pointer
|
||||
*
|
||||
* @param topOfMainStack Main Stack Pointer
|
||||
*
|
||||
* Assign the value mainStackPointer to the MSP
|
||||
* (main stack pointer) Cortex processor register
|
||||
*/
|
||||
void __set_MSP(uint32_t topOfMainStack) __attribute__( ( naked ) );
|
||||
void __set_MSP(uint32_t topOfMainStack)
|
||||
{
|
||||
__ASM volatile ("MSR msp, %0\n\t"
|
||||
"BX lr \n\t" : : "r" (topOfMainStack) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Base Priority value
|
||||
*
|
||||
* @return BasePriority
|
||||
*
|
||||
* Return the content of the base priority register
|
||||
*/
|
||||
uint32_t __get_BASEPRI(void)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Base Priority value
|
||||
*
|
||||
* @param basePri BasePriority
|
||||
*
|
||||
* Set the base priority register
|
||||
*/
|
||||
void __set_BASEPRI(uint32_t value)
|
||||
{
|
||||
__ASM volatile ("MSR basepri, %0" : : "r" (value) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Priority Mask value
|
||||
*
|
||||
* @return PriMask
|
||||
*
|
||||
* Return state of the priority mask bit from the priority mask register
|
||||
*/
|
||||
uint32_t __get_PRIMASK(void)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("MRS %0, primask" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Priority Mask value
|
||||
*
|
||||
* @param priMask PriMask
|
||||
*
|
||||
* Set the priority mask bit in the priority mask register
|
||||
*/
|
||||
void __set_PRIMASK(uint32_t priMask)
|
||||
{
|
||||
__ASM volatile ("MSR primask, %0" : : "r" (priMask) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Fault Mask value
|
||||
*
|
||||
* @return FaultMask
|
||||
*
|
||||
* Return the content of the fault mask register
|
||||
*/
|
||||
uint32_t __get_FAULTMASK(void)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Fault Mask value
|
||||
*
|
||||
* @param faultMask faultMask value
|
||||
*
|
||||
* Set the fault mask register
|
||||
*/
|
||||
void __set_FAULTMASK(uint32_t faultMask)
|
||||
{
|
||||
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Control Register value
|
||||
*
|
||||
* @return Control value
|
||||
*
|
||||
* Return the content of the control register
|
||||
*/
|
||||
uint32_t __get_CONTROL(void)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("MRS %0, control" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Control Register value
|
||||
*
|
||||
* @param control Control value
|
||||
*
|
||||
* Set the control register
|
||||
*/
|
||||
void __set_CONTROL(uint32_t control)
|
||||
{
|
||||
__ASM volatile ("MSR control, %0" : : "r" (control) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reverse byte order in integer value
|
||||
*
|
||||
* @param value value to reverse
|
||||
* @return reversed value
|
||||
*
|
||||
* Reverse byte order in integer value
|
||||
*/
|
||||
uint32_t __REV(uint32_t value)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reverse byte order in unsigned short value
|
||||
*
|
||||
* @param value value to reverse
|
||||
* @return reversed value
|
||||
*
|
||||
* Reverse byte order in unsigned short value
|
||||
*/
|
||||
uint32_t __REV16(uint16_t value)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reverse byte order in signed short value with sign extension to integer
|
||||
*
|
||||
* @param value value to reverse
|
||||
* @return reversed value
|
||||
*
|
||||
* Reverse byte order in signed short value with sign extension to integer
|
||||
*/
|
||||
int32_t __REVSH(int16_t value)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reverse bit order of value
|
||||
*
|
||||
* @param value value to reverse
|
||||
* @return reversed value
|
||||
*
|
||||
* Reverse bit order of value
|
||||
*/
|
||||
uint32_t __RBIT(uint32_t value)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LDR Exclusive (8 bit)
|
||||
*
|
||||
* @param *addr address pointer
|
||||
* @return value of (*address)
|
||||
*
|
||||
* Exclusive LDR command for 8 bit value
|
||||
*/
|
||||
uint8_t __LDREXB(uint8_t *addr)
|
||||
{
|
||||
uint8_t result=0;
|
||||
|
||||
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LDR Exclusive (16 bit)
|
||||
*
|
||||
* @param *addr address pointer
|
||||
* @return value of (*address)
|
||||
*
|
||||
* Exclusive LDR command for 16 bit values
|
||||
*/
|
||||
uint16_t __LDREXH(uint16_t *addr)
|
||||
{
|
||||
uint16_t result=0;
|
||||
|
||||
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LDR Exclusive (32 bit)
|
||||
*
|
||||
* @param *addr address pointer
|
||||
* @return value of (*address)
|
||||
*
|
||||
* Exclusive LDR command for 32 bit values
|
||||
*/
|
||||
uint32_t __LDREXW(uint32_t *addr)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief STR Exclusive (8 bit)
|
||||
*
|
||||
* @param value value to store
|
||||
* @param *addr address pointer
|
||||
* @return successful / failed
|
||||
*
|
||||
* Exclusive STR command for 8 bit values
|
||||
*/
|
||||
uint32_t __STREXB(uint8_t value, uint8_t *addr)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief STR Exclusive (16 bit)
|
||||
*
|
||||
* @param value value to store
|
||||
* @param *addr address pointer
|
||||
* @return successful / failed
|
||||
*
|
||||
* Exclusive STR command for 16 bit values
|
||||
*/
|
||||
uint32_t __STREXH(uint16_t value, uint16_t *addr)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief STR Exclusive (32 bit)
|
||||
*
|
||||
* @param value value to store
|
||||
* @param *addr address pointer
|
||||
* @return successful / failed
|
||||
*
|
||||
* Exclusive STR command for 32 bit values
|
||||
*/
|
||||
uint32_t __STREXW(uint32_t value, uint32_t *addr)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("strex %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
#elif (defined (__TASKING__)) /*------------------ TASKING Compiler ---------------------*/
|
||||
/* TASKING carm specific functions */
|
||||
|
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||
* Please use "carm -?i" to get an up to date list of all instrinsics,
|
||||
* Including the CMSIS ones.
|
||||
*/
|
||||
|
||||
#endif
|
359
firmware/src/cr_startup_lpc13.c
Normal file
359
firmware/src/cr_startup_lpc13.c
Normal file
|
@ -0,0 +1,359 @@
|
|||
//*****************************************************************************
|
||||
// +--+
|
||||
// | ++----+
|
||||
// +-++ |
|
||||
// | |
|
||||
// +-+--+ |
|
||||
// | +--+--+
|
||||
// +----+ Copyright (c) 2009 Code Red Technologies Ltd.
|
||||
//
|
||||
// Microcontroller Startup code for use with Red Suite
|
||||
//
|
||||
// Software License Agreement
|
||||
//
|
||||
// The software is owned by Code Red Technologies and/or its suppliers, and is
|
||||
// protected under applicable copyright laws. All rights are reserved. Any
|
||||
// use in violation of the foregoing restrictions may subject the user to criminal
|
||||
// sanctions under applicable laws, as well as to civil liability for the breach
|
||||
// of the terms and conditions of this license.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
|
||||
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
|
||||
// USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT
|
||||
// TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH
|
||||
// CODE RED TECHNOLOGIES LTD.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#define WEAK __attribute__ ((weak))
|
||||
#define ALIAS(f) __attribute__ ((weak, alias (#f)))
|
||||
|
||||
// Code Red - if CMSIS is being used, then SystemInit() routine
|
||||
// will be called by startup code rather than in application's main()
|
||||
#ifdef __USE_CMSIS
|
||||
#include "system_LPC13xx.h"
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Forward declaration of the default handlers. These are aliased.
|
||||
// When the application defines a handler (with the same name), this will
|
||||
// automatically take precedence over these weak definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
void Reset_Handler(void);
|
||||
void ResetISR(void) ALIAS(Reset_Handler);
|
||||
WEAK void NMI_Handler(void);
|
||||
WEAK void HardFault_Handler(void);
|
||||
WEAK void MemManage_Handler(void);
|
||||
WEAK void BusFault_Handler(void);
|
||||
WEAK void UsageFault_Handler(void);
|
||||
WEAK void SVCall_Handler(void);
|
||||
WEAK void DebugMon_Handler(void);
|
||||
WEAK void PendSV_Handler(void);
|
||||
WEAK void SysTick_Handler(void);
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Forward declaration of the specific IRQ handlers. These are aliased
|
||||
// to the IntDefaultHandler, which is a 'forever' loop. When the application
|
||||
// defines a handler (with the same name), this will automatically take
|
||||
// precedence over these weak definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
void I2C_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void TIMER16_0_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void TIMER16_1_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void TIMER32_0_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void TIMER32_1_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void SSP_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void UART_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void USB_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void USB_FIQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void ADC_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void WDT_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void BOD_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void FMC_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void PIOINT3_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void PIOINT2_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void PIOINT1_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void PIOINT0_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
void WAKEUP_IRQHandler (void) ALIAS(IntDefaultHandler);
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// The entry point for the application.
|
||||
// __main() is the entry point for redlib based applications
|
||||
// main() is the entry point for newlib based applications
|
||||
//
|
||||
//*****************************************************************************
|
||||
extern WEAK void __main(void);
|
||||
extern WEAK void main(void);
|
||||
//*****************************************************************************
|
||||
//
|
||||
// External declaration for the pointer to the stack top from the Linker Script
|
||||
//
|
||||
//*****************************************************************************
|
||||
extern void _vStackTop;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// The vector table. Note that the proper constructs must be placed on this to
|
||||
// ensure that it ends up at physical address 0x0000.0000.
|
||||
//
|
||||
//*****************************************************************************
|
||||
__attribute__ ((section(".isr_vector")))
|
||||
void (* const g_pfnVectors[])(void) =
|
||||
{
|
||||
// Core Level - CM3
|
||||
(void *)&_vStackTop, // The initial stack pointer
|
||||
Reset_Handler, // The reset handler
|
||||
NMI_Handler, // The NMI handler
|
||||
HardFault_Handler, // The hard fault handler
|
||||
MemManage_Handler, // The MPU fault handler
|
||||
BusFault_Handler, // The bus fault handler
|
||||
UsageFault_Handler, // The usage fault handler
|
||||
0, // Reserved
|
||||
0, // Reserved
|
||||
0, // Reserved
|
||||
0, // Reserved
|
||||
SVCall_Handler, // SVCall handler
|
||||
DebugMon_Handler, // Debug monitor handler
|
||||
0, // Reserved
|
||||
PendSV_Handler, // The PendSV handler
|
||||
SysTick_Handler, // The SysTick handler
|
||||
|
||||
|
||||
|
||||
// Wakeup sources (40 ea.) for the I/O pins:
|
||||
// PIO0 (0:11)
|
||||
// PIO1 (0:11)
|
||||
// PIO2 (0:11)
|
||||
// PIO3 (0:3)
|
||||
WAKEUP_IRQHandler, // PIO0_0 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO0_1 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO0_2 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO0_3 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO0_4 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO0_5 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO0_6 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO0_7 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO0_8 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO0_9 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO0_10 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO0_11 Wakeup
|
||||
|
||||
WAKEUP_IRQHandler, // PIO1_0 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO1_1 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO1_2 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO1_3 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO1_4 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO1_5 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO1_6 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO1_7 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO1_8 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO1_9 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO1_10 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO1_11 Wakeup
|
||||
|
||||
WAKEUP_IRQHandler, // PIO2_0 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO2_1 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO2_2 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO2_3 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO2_4 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO2_5 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO2_6 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO2_7 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO2_8 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO2_9 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO2_10 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO2_11 Wakeup
|
||||
|
||||
WAKEUP_IRQHandler, // PIO3_0 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO3_1 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO3_2 Wakeup
|
||||
WAKEUP_IRQHandler, // PIO3_3 Wakeup
|
||||
|
||||
I2C_IRQHandler, // I2C0
|
||||
TIMER16_0_IRQHandler, // CT16B0 (16-bit Timer 0)
|
||||
TIMER16_1_IRQHandler, // CT16B1 (16-bit Timer 1)
|
||||
TIMER32_0_IRQHandler, // CT32B0 (32-bit Timer 0)
|
||||
TIMER32_1_IRQHandler, // CT32B1 (32-bit Timer 1)
|
||||
SSP_IRQHandler, // SSP0
|
||||
UART_IRQHandler, // UART0
|
||||
|
||||
USB_IRQHandler, // USB IRQ
|
||||
USB_FIQHandler, // USB FIQ
|
||||
|
||||
ADC_IRQHandler, // ADC (A/D Converter)
|
||||
WDT_IRQHandler, // WDT (Watchdog Timer)
|
||||
BOD_IRQHandler, // BOD (Brownout Detect)
|
||||
FMC_IRQHandler, // Flash (IP2111 Flash Memory Controller)
|
||||
PIOINT3_IRQHandler, // PIO INT3
|
||||
PIOINT2_IRQHandler, // PIO INT2
|
||||
PIOINT1_IRQHandler, // PIO INT1
|
||||
PIOINT0_IRQHandler, // PIO INT0
|
||||
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// The following are constructs created by the linker, indicating where the
|
||||
// the "data" and "bss" segments reside in memory. The initializers for the
|
||||
// for the "data" segment resides immediately following the "text" segment.
|
||||
//
|
||||
//*****************************************************************************
|
||||
extern unsigned long _etext;
|
||||
extern unsigned long _data;
|
||||
extern unsigned long _edata;
|
||||
extern unsigned long _bss;
|
||||
extern unsigned long _ebss;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// This is the code that gets called when the processor first starts execution
|
||||
// following a reset event. Only the absolutely necessary set is performed,
|
||||
// after which the application supplied entry() routine is called. Any fancy
|
||||
// actions (such as making decisions based on the reset cause register, and
|
||||
// resetting the bits in that register) are left solely in the hands of the
|
||||
// application.
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
//ResetISR(void)
|
||||
Reset_Handler(void)
|
||||
{
|
||||
unsigned long *pulSrc, *pulDest;
|
||||
|
||||
//
|
||||
// Copy the data segment initializers from flash to SRAM.
|
||||
//
|
||||
pulSrc = &_etext;
|
||||
for(pulDest = &_data; pulDest < &_edata; )
|
||||
{
|
||||
*pulDest++ = *pulSrc++;
|
||||
}
|
||||
|
||||
//
|
||||
// Zero fill the bss segment. This is done with inline assembly since this
|
||||
// will clear the value of pulDest if it is not kept in a register.
|
||||
//
|
||||
__asm(" ldr r0, =_bss\n"
|
||||
" ldr r1, =_ebss\n"
|
||||
" mov r2, #0\n"
|
||||
" .thumb_func\n"
|
||||
"zero_loop:\n"
|
||||
" cmp r0, r1\n"
|
||||
" it lt\n"
|
||||
" strlt r2, [r0], #4\n"
|
||||
" blt zero_loop");
|
||||
|
||||
#ifdef __USE_CMSIS
|
||||
SystemInit();
|
||||
#endif
|
||||
|
||||
//
|
||||
// Call the application's entry point.
|
||||
// __main() is the entry point for redlib based applications (which calls main())
|
||||
// main() is the entry point for newlib based applications
|
||||
//
|
||||
if (__main)
|
||||
__main() ;
|
||||
else
|
||||
main() ;
|
||||
|
||||
//
|
||||
// main() shouldn't return, but if it does, we'll just enter an infinite loop
|
||||
//
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// This is the code that gets called when the processor receives a NMI. This
|
||||
// simply enters an infinite loop, preserving the system state for examination
|
||||
// by a debugger.
|
||||
//
|
||||
//*****************************************************************************
|
||||
void NMI_Handler(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void MemManage_Handler(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void BusFault_Handler(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void UsageFault_Handler(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void SVCall_Handler(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void DebugMon_Handler(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void PendSV_Handler(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Processor ends up here if an unexpected interrupt occurs or a handler
|
||||
// is not present in the application code.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
static void IntDefaultHandler(void)
|
||||
{
|
||||
//
|
||||
// Go into an infinite loop.
|
||||
//
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
119
firmware/src/edubrm.c
Normal file
119
firmware/src/edubrm.c
Normal file
|
@ -0,0 +1,119 @@
|
|||
#include "LPC13xx.h"
|
||||
#include "type.h"
|
||||
|
||||
#include "usb.h"
|
||||
#include "usbcfg.h"
|
||||
#include "usbhw.h"
|
||||
#include "usbcore.h"
|
||||
#include "cdc.h"
|
||||
#include "cdcuser.h"
|
||||
#include "serial.h"
|
||||
#include "vcomdemo.h"
|
||||
#include "mscuser.h"
|
||||
#include "memory.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
|
||||
#include "edubrm.h"
|
||||
|
||||
|
||||
#define mainLED_BIT ( 7 )
|
||||
|
||||
void VCOM_Brm2Usb(void) {
|
||||
/*
|
||||
static char serBuf [USB_CDC_BUFSIZE];
|
||||
int numBytesRead, numAvailByte;
|
||||
|
||||
|
||||
serBuf[0] = 'A';
|
||||
numBytesRead = 1;
|
||||
|
||||
/* ser_AvailChar (&numAvailByte);
|
||||
if (numAvailByte > 0) {
|
||||
if (CDC_DepInEmpty) {
|
||||
numBytesRead = ser_Read (&serBuf[0], &numAvailByte);
|
||||
|
||||
CDC_DepInEmpty = 0;
|
||||
|
||||
USB_WriteEP (CDC_DEP_IN, (unsigned char *)&serBuf[0], numBytesRead);
|
||||
}
|
||||
/*
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
static char cmdInbuffer[256];
|
||||
int cmdInbufferIndex = 0;
|
||||
|
||||
int checkForCommand(void) {
|
||||
int i=0;
|
||||
for (i=0;i<cmdInbufferIndex;i++) {
|
||||
if (cmdInbuffer[i] == '\n' ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static unsigned long ulLEDState = 1;
|
||||
|
||||
void enableLED() {
|
||||
LPC_GPIO0->DIR |= ( 0x1 << mainLED_BIT );
|
||||
}
|
||||
|
||||
void disableLED() {
|
||||
LPC_GPIO0->DIR |= ( 0x0 << mainLED_BIT );
|
||||
}
|
||||
|
||||
void toggleLED( ){
|
||||
ulLEDState = !ulLEDState;
|
||||
LPC_GPIO0->MASKED_ACCESS[ ( 1 << mainLED_BIT) ] = ( ulLEDState << mainLED_BIT );
|
||||
|
||||
}
|
||||
|
||||
void sendToUSB(char *string) {
|
||||
USB_WriteEP (CDC_DEP_IN, string, strlen(string));
|
||||
}
|
||||
|
||||
|
||||
void commandReceived(char * receivedCommand) {
|
||||
|
||||
if (strcmp("PING", receivedCommand) == 0) {
|
||||
//echo back
|
||||
sendToUSB("PONG\n");
|
||||
toggleLED();
|
||||
} else if (strcmp("VERSION", receivedCommand) == 0) {
|
||||
sendToUSB(VERSION);
|
||||
toggleLED();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void VCOM_Usb2Brm(void) {
|
||||
static char serBuf [32];
|
||||
int numBytesToRead, numBytesRead, numAvailByte;
|
||||
int i=0;
|
||||
static char receivedCommand[128];
|
||||
|
||||
CDC_OutBufAvailChar (&numAvailByte);
|
||||
if (numAvailByte > 0) {
|
||||
numBytesToRead = numAvailByte > 32 ? 32 : numAvailByte;
|
||||
numBytesRead = CDC_RdOutBuf (&serBuf[0], &numBytesToRead);
|
||||
for (i=0;i<numBytesRead;i++) { //TODO: replace with memcpy
|
||||
cmdInbuffer[cmdInbufferIndex++] = serBuf[i];
|
||||
}
|
||||
int command = checkForCommand();
|
||||
if (command != 0) {
|
||||
//there is some command
|
||||
cmdInbufferIndex = 0;
|
||||
memset(receivedCommand,sizeof(receivedCommand), 0);
|
||||
memcpy(receivedCommand, (unsigned char *)&cmdInbuffer[0], command);
|
||||
//USB_WriteEP (CDC_DEP_IN, (unsigned char *)&cmdInbuffer[0], command);
|
||||
commandReceived(receivedCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
6
firmware/src/edubrm.h
Normal file
6
firmware/src/edubrm.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef EDUBRM_H
|
||||
#define EDUBRM_H
|
||||
|
||||
#define VERSION "0.0000001 pre-alpha\n"
|
||||
|
||||
#endif
|
708
firmware/src/mscuser.c
Normal file
708
firmware/src/mscuser.c
Normal file
|
@ -0,0 +1,708 @@
|
|||
/*----------------------------------------------------------------------------
|
||||
* U S B - K e r n e l
|
||||
*----------------------------------------------------------------------------
|
||||
* Name: mscuser.c
|
||||
* Purpose: Mass Storage Class 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 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 SCSI_READ12, SCSI_WRITE12
|
||||
* V1.00 Initial Version
|
||||
*---------------------------------------------------------------------------*/
|
||||
#include "type.h"
|
||||
|
||||
#include "usb.h"
|
||||
#include "msc.h"
|
||||
#include "usbcfg.h"
|
||||
#include "usbhw.h"
|
||||
#include "usbcore.h"
|
||||
#include "mscuser.h"
|
||||
#include "memory.h"
|
||||
|
||||
|
||||
uint8_t Memory[MSC_MemorySize]; /* MSC RAM */
|
||||
|
||||
uint32_t MemOK; /* Memory OK */
|
||||
|
||||
uint32_t Offset; /* R/W Offset */
|
||||
uint32_t Length; /* R/W Length */
|
||||
|
||||
uint8_t BulkStage = MSC_BS_CBW; /* Bulk Stage */
|
||||
|
||||
uint8_t BulkBuf[MSC_MAX_PACKET] __attribute__ ((aligned (4))); /* Bulk In/Out Buffer */
|
||||
uint8_t BulkLen; /* Bulk In/Out Length */
|
||||
|
||||
MSC_CBW CBW; /* Command Block Wrapper */
|
||||
MSC_CSW CSW; /* Command Status Wrapper */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Set Stall for MSC Endpoint
|
||||
* Parameters: EPNum: Endpoint Number
|
||||
* EPNum.0..3: Address
|
||||
* EPNum.7: Dir
|
||||
* Return Value: None
|
||||
*/
|
||||
|
||||
void MSC_SetStallEP (uint32_t EPNum) { /* set EP halt status according stall status */
|
||||
USB_SetStallEP(EPNum);
|
||||
USB_EndPointHalt |= (EPNum & 0x80) ? ((1 << 16) << (EPNum & 0x0F)) : (1 << EPNum);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
|
||||
|
||||
USB_EndPointStall = 0x00000000; /* EP must stay stalled */
|
||||
CSW.dSignature = 0; /* invalid signature */
|
||||
|
||||
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;
|
||||
|
||||
if (Length > MSC_MAX_PACKET) {
|
||||
n = MSC_MAX_PACKET;
|
||||
} else {
|
||||
n = Length;
|
||||
}
|
||||
|
||||
if ((Offset + n) > MSC_MemorySize) {
|
||||
n = MSC_MemorySize - Offset;
|
||||
BulkStage = MSC_BS_DATA_IN_LAST_STALL;
|
||||
}
|
||||
|
||||
USB_WriteEP(MSC_EP_IN, &Memory[Offset], n);
|
||||
Offset += n;
|
||||
Length -= n;
|
||||
|
||||
CSW.dDataResidue -= n;
|
||||
|
||||
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) {
|
||||
uint32_t n;
|
||||
|
||||
if ((Offset + BulkLen) > MSC_MemorySize) {
|
||||
BulkLen = MSC_MemorySize - Offset;
|
||||
BulkStage = MSC_BS_CSW;
|
||||
MSC_SetStallEP(MSC_EP_OUT);
|
||||
}
|
||||
|
||||
for (n = 0; n < BulkLen; n++) {
|
||||
Memory[Offset + n] = BulkBuf[n];
|
||||
}
|
||||
|
||||
Offset += BulkLen;
|
||||
Length -= BulkLen;
|
||||
|
||||
CSW.dDataResidue -= BulkLen;
|
||||
|
||||
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) {
|
||||
uint32_t n;
|
||||
|
||||
if ((Offset + BulkLen) > MSC_MemorySize) {
|
||||
BulkLen = MSC_MemorySize - Offset;
|
||||
BulkStage = MSC_BS_CSW;
|
||||
MSC_SetStallEP(MSC_EP_OUT);
|
||||
}
|
||||
|
||||
for (n = 0; n < BulkLen; n++) {
|
||||
if (Memory[Offset + n] != BulkBuf[n]) {
|
||||
MemOK = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
n = (CBW.CB[2] << 24) |
|
||||
(CBW.CB[3] << 16) |
|
||||
(CBW.CB[4] << 8) |
|
||||
(CBW.CB[5] << 0);
|
||||
|
||||
Offset = n * MSC_BlockSize;
|
||||
|
||||
/* Number of Blocks to transfer */
|
||||
switch (CBW.CB[0]) {
|
||||
case SCSI_READ10:
|
||||
case SCSI_WRITE10:
|
||||
case SCSI_VERIFY10:
|
||||
n = (CBW.CB[7] << 8) |
|
||||
(CBW.CB[8] << 0);
|
||||
break;
|
||||
|
||||
case SCSI_READ12:
|
||||
case SCSI_WRITE12:
|
||||
n = (CBW.CB[6] << 24) |
|
||||
(CBW.CB[7] << 16) |
|
||||
(CBW.CB[8] << 8) |
|
||||
(CBW.CB[9] << 0);
|
||||
break;
|
||||
}
|
||||
|
||||
Length = n * MSC_BlockSize;
|
||||
|
||||
if (CBW.dDataLength == 0) { /* host requests no data */
|
||||
CSW.bStatus = CSW_CMD_FAILED;
|
||||
MSC_SetCSW();
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (CBW.dDataLength != Length) {
|
||||
if ((CBW.bmFlags & 0x80) != 0) { /* stall appropriate EP */
|
||||
MSC_SetStallEP(MSC_EP_IN);
|
||||
} else {
|
||||
MSC_SetStallEP(MSC_EP_OUT);
|
||||
}
|
||||
|
||||
CSW.bStatus = CSW_CMD_FAILED;
|
||||
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) {
|
||||
MSC_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;
|
||||
|
||||
BulkStage = MSC_BS_DATA_IN_LAST;
|
||||
|
||||
USB_WriteEP(MSC_EP_IN, BulkBuf, BulkLen);
|
||||
|
||||
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) {
|
||||
MSC_SetStallEP(MSC_EP_IN);
|
||||
} else {
|
||||
MSC_SetStallEP(MSC_EP_OUT);
|
||||
}
|
||||
}
|
||||
|
||||
CSW.bStatus = CSW_CMD_PASSED;
|
||||
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] = 0x02; /* Sense Key */
|
||||
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] = 0x30; /* ASC */
|
||||
BulkBuf[13] = 0x01; /* ASCQ */
|
||||
BulkBuf[14] = 0x00;
|
||||
BulkBuf[15] = 0x00;
|
||||
BulkBuf[16] = 0x00;
|
||||
BulkBuf[17] = 0x00;
|
||||
|
||||
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] = 'K'; /* Vendor Identification */
|
||||
BulkBuf[ 9] = 'e';
|
||||
BulkBuf[10] = 'i';
|
||||
BulkBuf[11] = 'l';
|
||||
BulkBuf[12] = ' ';
|
||||
BulkBuf[13] = ' ';
|
||||
BulkBuf[14] = ' ';
|
||||
BulkBuf[15] = ' ';
|
||||
|
||||
BulkBuf[16] = 'L'; /* Product Identification */
|
||||
BulkBuf[17] = 'P';
|
||||
BulkBuf[18] = 'C';
|
||||
BulkBuf[19] = '1';
|
||||
BulkBuf[20] = '3';
|
||||
BulkBuf[21] = '4';
|
||||
BulkBuf[22] = 'x';
|
||||
BulkBuf[23] = ' ';
|
||||
BulkBuf[24] = 'D';
|
||||
BulkBuf[25] = 'i';
|
||||
BulkBuf[26] = 's';
|
||||
BulkBuf[27] = 'k';
|
||||
BulkBuf[28] = ' ';
|
||||
BulkBuf[29] = ' ';
|
||||
BulkBuf[30] = ' ';
|
||||
BulkBuf[31] = ' ';
|
||||
|
||||
BulkBuf[32] = '1'; /* Product Revision Level */
|
||||
BulkBuf[33] = '.';
|
||||
BulkBuf[34] = '0';
|
||||
BulkBuf[35] = ' ';
|
||||
|
||||
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_BlockSize >> 24) & 0xFF;
|
||||
BulkBuf[ 5] = (MSC_BlockSize >> 16) & 0xFF;
|
||||
BulkBuf[ 6] = (MSC_BlockSize >> 8) & 0xFF;
|
||||
BulkBuf[ 7] = (MSC_BlockSize >> 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_BlockSize >> 16) & 0xFF;
|
||||
BulkBuf[10] = (MSC_BlockSize >> 8) & 0xFF;
|
||||
BulkBuf[11] = (MSC_BlockSize >> 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();
|
||||
} 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:
|
||||
goto fail;
|
||||
case SCSI_MEDIA_REMOVAL:
|
||||
goto fail;
|
||||
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:
|
||||
case SCSI_READ12:
|
||||
if (MSC_RWSetup()) {
|
||||
if ((CBW.bmFlags & 0x80) != 0) {
|
||||
BulkStage = MSC_BS_DATA_IN;
|
||||
MSC_MemoryRead();
|
||||
} else { /* direction mismatch */
|
||||
MSC_SetStallEP(MSC_EP_OUT);
|
||||
CSW.bStatus = CSW_PHASE_ERROR;
|
||||
MSC_SetCSW();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCSI_WRITE10:
|
||||
case SCSI_WRITE12:
|
||||
if (MSC_RWSetup()) {
|
||||
if ((CBW.bmFlags & 0x80) == 0) {
|
||||
BulkStage = MSC_BS_DATA_OUT;
|
||||
} else { /* direction mismatch */
|
||||
MSC_SetStallEP(MSC_EP_IN);
|
||||
CSW.bStatus = CSW_PHASE_ERROR;
|
||||
MSC_SetCSW();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCSI_VERIFY10:
|
||||
if ((CBW.CB[1] & 0x02) == 0) {
|
||||
// BYTCHK = 0 -> CRC Check (not implemented)
|
||||
CSW.bStatus = CSW_CMD_PASSED;
|
||||
MSC_SetCSW();
|
||||
break;
|
||||
}
|
||||
if (MSC_RWSetup()) {
|
||||
if ((CBW.bmFlags & 0x80) == 0) {
|
||||
BulkStage = MSC_BS_DATA_OUT;
|
||||
MemOK = TRUE;
|
||||
} else {
|
||||
MSC_SetStallEP(MSC_EP_IN);
|
||||
CSW.bStatus = CSW_PHASE_ERROR;
|
||||
MSC_SetCSW();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Invalid CBW */
|
||||
MSC_SetStallEP(MSC_EP_IN);
|
||||
/* set EP to stay stalled */
|
||||
USB_EndPointStall |= (MSC_EP_IN & 0x80) ? ((1 << 16) << (MSC_EP_IN & 0x0F)) : (1 << MSC_EP_IN);
|
||||
MSC_SetStallEP(MSC_EP_OUT);
|
||||
/* set EP to stay stalled */
|
||||
USB_EndPointStall |= (MSC_EP_OUT & 0x80) ? ((1 << 16) << (MSC_EP_OUT & 0x0F)) : (1 << 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:
|
||||
case SCSI_READ12:
|
||||
MSC_MemoryRead();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MSC_BS_DATA_IN_LAST:
|
||||
MSC_SetCSW();
|
||||
break;
|
||||
case MSC_BS_DATA_IN_LAST_STALL:
|
||||
MSC_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 = 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:
|
||||
case SCSI_WRITE12:
|
||||
MSC_MemoryWrite();
|
||||
break;
|
||||
case SCSI_VERIFY10:
|
||||
MSC_MemoryVerify();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MSC_SetStallEP(MSC_EP_OUT);
|
||||
CSW.bStatus = CSW_PHASE_ERROR;
|
||||
MSC_SetCSW();
|
||||
break;
|
||||
}
|
||||
}
|
243
firmware/src/serial.c
Normal file
243
firmware/src/serial.c
Normal file
|
@ -0,0 +1,243 @@
|
|||
/*----------------------------------------------------------------------------
|
||||
* Name: serial.c
|
||||
* Purpose: serial port handling for LPC134x
|
||||
* 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.
|
||||
*---------------------------------------------------------------------------*/
|
||||
#include "LPC13xx.h" // LPC13xx definitions
|
||||
#include "type.h"
|
||||
#include "serial.h"
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Defines for ring buffers
|
||||
*---------------------------------------------------------------------------*/
|
||||
#define SER_BUF_SIZE (128) // serial buffer in bytes (power 2)
|
||||
#define SER_BUF_MASK (SER_BUF_SIZE-1ul) // buffer size mask
|
||||
|
||||
/* Buffer read / write macros */
|
||||
#define SER_BUF_RESET(serBuf) (serBuf.rdIdx = serBuf.wrIdx = 0)
|
||||
#define SER_BUF_WR(serBuf, dataIn) (serBuf.data[SER_BUF_MASK & serBuf.wrIdx++] = (dataIn))
|
||||
#define SER_BUF_RD(serBuf) (serBuf.data[SER_BUF_MASK & serBuf.rdIdx++])
|
||||
#define SER_BUF_EMPTY(serBuf) (serBuf.rdIdx == serBuf.wrIdx)
|
||||
#define SER_BUF_FULL(serBuf) (serBuf.rdIdx == serBuf.wrIdx+1)
|
||||
#define SER_BUF_COUNT(serBuf) (SER_BUF_MASK & (serBuf.wrIdx - serBuf.rdIdx))
|
||||
|
||||
// buffer type
|
||||
typedef struct __SER_BUF_T {
|
||||
unsigned char data[SER_BUF_SIZE];
|
||||
unsigned int wrIdx;
|
||||
unsigned int rdIdx;
|
||||
} SER_BUF_T;
|
||||
|
||||
unsigned long ser_txRestart; // NZ if TX restart is required
|
||||
unsigned short ser_lineState; // ((msr << 8) | (lsr))
|
||||
SER_BUF_T ser_out; // Serial data buffers
|
||||
SER_BUF_T ser_in;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
open the serial port
|
||||
*---------------------------------------------------------------------------*/
|
||||
void ser_OpenPort (void) {
|
||||
|
||||
NVIC_DisableIRQ(UART_IRQn);
|
||||
|
||||
LPC_IOCON->PIO1_6 &= ~0x07; /* UART I/O config */
|
||||
LPC_IOCON->PIO1_6 |= 0x01; /* UART RXD */
|
||||
LPC_IOCON->PIO1_7 &= ~0x07;
|
||||
LPC_IOCON->PIO1_7 |= 0x01; /* UART TXD */
|
||||
/* Enable UART clock */
|
||||
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
|
||||
LPC_SYSCON->UARTCLKDIV = 0x1; /* divided by 1 */
|
||||
return;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
close the serial port
|
||||
*---------------------------------------------------------------------------*/
|
||||
void ser_ClosePort (void) {
|
||||
LPC_IOCON->PIO1_6 &= ~0x07; /* UART I/O config */
|
||||
LPC_IOCON->PIO1_7 &= ~0x07;
|
||||
|
||||
/* Disable the interrupt in the VIC and UART controllers */
|
||||
LPC_UART->IER = 0;
|
||||
NVIC_DisableIRQ(UART_IRQn);
|
||||
return;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
initialize the serial port
|
||||
*---------------------------------------------------------------------------*/
|
||||
void ser_InitPort (unsigned long baudrate, unsigned int databits,
|
||||
unsigned int parity, unsigned int stopbits) {
|
||||
|
||||
uint8_t lcr_p, lcr_s, lcr_d;
|
||||
uint32_t dll;
|
||||
uint32_t Fdiv;
|
||||
|
||||
switch (databits) {
|
||||
case 5: // 5 Data bits
|
||||
lcr_d = 0x00;
|
||||
break;
|
||||
case 6: // 6 Data bits
|
||||
lcr_d = 0x01;
|
||||
break;
|
||||
case 7: // 7 Data bits
|
||||
lcr_d = 0x02;
|
||||
break;
|
||||
case 8: // 8 Data bits
|
||||
default:
|
||||
lcr_d = 0x03;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (stopbits) {
|
||||
case 1: // 1,5 Stop bits
|
||||
case 2: // 2 Stop bits
|
||||
lcr_s = 0x04;
|
||||
break;
|
||||
case 0: // 1 Stop bit
|
||||
default:
|
||||
lcr_s = 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (parity) {
|
||||
case 1: // Parity Odd
|
||||
lcr_p = 0x08;
|
||||
break;
|
||||
case 2: // Parity Even
|
||||
lcr_p = 0x18;
|
||||
break;
|
||||
case 3: // Parity Mark
|
||||
lcr_p = 0x28;
|
||||
break;
|
||||
case 4: // Parity Space
|
||||
lcr_p = 0x38;
|
||||
break;
|
||||
case 0: // Parity None
|
||||
default:
|
||||
lcr_p = 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
SER_BUF_RESET(ser_out); // reset out buffer
|
||||
SER_BUF_RESET(ser_in); // reset in buffer
|
||||
|
||||
/* Note that the pclk is 24,0 MHz. (48.0 MHz / 2) */
|
||||
/* 24 MHz PCLK generates also rates for 115200, 57600 baud */
|
||||
Fdiv = LPC_SYSCON->UARTCLKDIV;
|
||||
dll = (((SystemCoreClock/LPC_SYSCON->SYSAHBCLKDIV)/Fdiv)/16)/baudrate ; /*baud rate */
|
||||
LPC_UART->FDR = 0; // Fractional divider not used
|
||||
LPC_UART->LCR = 0x80 | lcr_d | lcr_p | lcr_s; // Data bits, Parity, Stop bit
|
||||
LPC_UART->DLL = dll; // Baud Rate depending on PCLK
|
||||
LPC_UART->DLM = (dll >> 8); // High divisor latch
|
||||
LPC_UART->LCR = 0x00 | lcr_d | lcr_p | lcr_s; // DLAB = 0
|
||||
LPC_UART->IER = 0x03; // Enable TX/RX interrupts
|
||||
|
||||
LPC_UART->FCR = 0x07; /* Enable and reset TX and RX FIFO. */
|
||||
ser_txRestart = 1; // TX fifo is empty
|
||||
|
||||
/* Enable the UART Interrupt */
|
||||
NVIC_EnableIRQ(UART_IRQn);
|
||||
return;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
read data from serial port
|
||||
*---------------------------------------------------------------------------*/
|
||||
int ser_Read (char *buffer, const int *length) {
|
||||
int bytesToRead, bytesRead;
|
||||
|
||||
/* Read *length bytes, block if *bytes are not avaialable */
|
||||
bytesToRead = *length;
|
||||
bytesToRead = (bytesToRead < (*length)) ? bytesToRead : (*length);
|
||||
bytesRead = bytesToRead;
|
||||
|
||||
while (bytesToRead--) {
|
||||
while (SER_BUF_EMPTY(ser_in)); // Block until data is available if none
|
||||
*buffer++ = SER_BUF_RD(ser_in);
|
||||
}
|
||||
return (bytesRead);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
write data to the serial port
|
||||
*---------------------------------------------------------------------------*/
|
||||
int ser_Write (const char *buffer, int *length) {
|
||||
int bytesToWrite, bytesWritten;
|
||||
|
||||
// Write *length bytes
|
||||
bytesToWrite = *length;
|
||||
bytesWritten = bytesToWrite;
|
||||
|
||||
while (!SER_BUF_EMPTY(ser_out)); // Block until space is available if none
|
||||
while (bytesToWrite) {
|
||||
SER_BUF_WR(ser_out, *buffer++); // Read Rx FIFO to buffer
|
||||
bytesToWrite--;
|
||||
}
|
||||
|
||||
if (ser_txRestart) {
|
||||
ser_txRestart = 0;
|
||||
LPC_UART->THR = SER_BUF_RD(ser_out); // Write to the Tx Register
|
||||
}
|
||||
|
||||
return (bytesWritten);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
check if character(s) are available at the serial interface
|
||||
*---------------------------------------------------------------------------*/
|
||||
void ser_AvailChar (int *availChar) {
|
||||
|
||||
*availChar = SER_BUF_COUNT(ser_in);
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
read the line state of the serial port
|
||||
*---------------------------------------------------------------------------*/
|
||||
void ser_LineState (unsigned short *lineState) {
|
||||
|
||||
*lineState = ser_lineState;
|
||||
ser_lineState = 0;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
serial port 1 interrupt
|
||||
*---------------------------------------------------------------------------*/
|
||||
void UART_IRQHandler(void)
|
||||
{
|
||||
volatile unsigned long iir;
|
||||
|
||||
iir = LPC_UART->IIR;
|
||||
|
||||
if ((iir & 0x4) || (iir & 0xC)) { // RDA or CTI pending
|
||||
while (LPC_UART->LSR & 0x01) { // Rx FIFO is not empty
|
||||
SER_BUF_WR(ser_in, LPC_UART->RBR); // Read Rx FIFO to buffer
|
||||
}
|
||||
}
|
||||
if ((iir & 0x2)) { // TXMIS pending
|
||||
if (SER_BUF_COUNT(ser_out) != 0) {
|
||||
LPC_UART->THR = SER_BUF_RD(ser_out); // Write to the Tx FIFO
|
||||
ser_txRestart = 0;
|
||||
}
|
||||
else {
|
||||
ser_txRestart = 1;
|
||||
}
|
||||
}
|
||||
ser_lineState = LPC_UART->LSR & 0x1E; // update linestate
|
||||
return;
|
||||
}
|
||||
|
||||
|
487
firmware/src/system_LPC13xx.c
Normal file
487
firmware/src/system_LPC13xx.c
Normal file
|
@ -0,0 +1,487 @@
|
|||
/**************************************************************************//**
|
||||
* @file system_LPC13xx.c
|
||||
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer Source File
|
||||
* for the NXP LPC13xx Device Series
|
||||
* @version V1.02
|
||||
* @date 18. February 2010
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2009 ARM Limited. All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* ARM Limited (ARM) is supplying this software for use with Cortex-M
|
||||
* processor based microcontrollers. This file can be freely distributed
|
||||
* within development tools that are supporting such ARM based processors.
|
||||
*
|
||||
* @par
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
|
||||
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
|
||||
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
|
||||
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
// ******** Code Red **************
|
||||
// * Changed USBCLK_SETUP to 1
|
||||
// * Changed SYSPLLCTRL_Val to 0x25
|
||||
// ********************************
|
||||
|
||||
#include <stdint.h>
|
||||
#include "LPC13xx.h"
|
||||
|
||||
/*
|
||||
//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
|
||||
*/
|
||||
|
||||
/*--------------------- Clock Configuration ----------------------------------
|
||||
//
|
||||
// <e> Clock Configuration
|
||||
// <e1> System Clock Setup
|
||||
// <e2> System Oscillator Enable
|
||||
// <o3.1> Select System Oscillator Frequency Range
|
||||
// <0=> 1 - 20 MHz
|
||||
// <1=> 15 - 25 MHz
|
||||
// </e2>
|
||||
// <e4> Watchdog Oscillator Enable
|
||||
// <o5.0..4> Select Divider for Fclkana
|
||||
// <0=> 2 <1=> 4 <2=> 6 <3=> 8
|
||||
// <4=> 10 <5=> 12 <6=> 14 <7=> 16
|
||||
// <8=> 18 <9=> 20 <10=> 22 <11=> 24
|
||||
// <12=> 26 <13=> 28 <14=> 30 <15=> 32
|
||||
// <16=> 34 <17=> 36 <18=> 38 <19=> 40
|
||||
// <20=> 42 <21=> 44 <22=> 46 <23=> 48
|
||||
// <24=> 50 <25=> 52 <26=> 54 <27=> 56
|
||||
// <28=> 58 <29=> 60 <30=> 62 <31=> 64
|
||||
// <o5.5..8> Select Watchdog Oscillator Analog Frequency (Fclkana)
|
||||
// <0=> Disabled
|
||||
// <1=> 0.5 MHz
|
||||
// <2=> 0.8 MHz
|
||||
// <3=> 1.1 MHz
|
||||
// <4=> 1.4 MHz
|
||||
// <5=> 1.6 MHz
|
||||
// <6=> 1.8 MHz
|
||||
// <7=> 2.0 MHz
|
||||
// <8=> 2.2 MHz
|
||||
// <9=> 2.4 MHz
|
||||
// <10=> 2.6 MHz
|
||||
// <11=> 2.7 MHz
|
||||
// <12=> 2.9 MHz
|
||||
// <13=> 3.1 MHz
|
||||
// <14=> 3.2 MHz
|
||||
// <15=> 3.4 MHz
|
||||
// </e4>
|
||||
// <o6> Select Input Clock for sys_pllclkin (Register: SYSPLLCLKSEL)
|
||||
// <0=> IRC Oscillator
|
||||
// <1=> System Oscillator
|
||||
// <2=> WDT Oscillator
|
||||
// <3=> Invalid
|
||||
// <e7> Use System PLL
|
||||
// <i> F_pll = M * F_in
|
||||
// <i> F_in must be in the range of 10 MHz to 25 MHz
|
||||
// <o8.0..4> M: PLL Multiplier Selection
|
||||
// <1-32><#-1>
|
||||
// <o8.5..6> P: PLL Divider Selection
|
||||
// <0=> 2
|
||||
// <1=> 4
|
||||
// <2=> 8
|
||||
// <3=> 16
|
||||
// <o8.7> DIRECT: Direct CCO Clock Output Enable
|
||||
// <o8.8> BYPASS: PLL Bypass Enable
|
||||
// </e7>
|
||||
// <o9> Select Input Clock for Main clock (Register: MAINCLKSEL)
|
||||
// <0=> IRC Oscillator
|
||||
// <1=> Input Clock to System PLL
|
||||
// <2=> WDT Oscillator
|
||||
// <3=> System PLL Clock Out
|
||||
// </e1>
|
||||
// <e10> USB Clock Setup
|
||||
// <e11> Use USB PLL
|
||||
// <i> F_pll = M * F_in
|
||||
// <i> F_in must be in the range of 10 MHz to 25 MHz
|
||||
// <o12.0..1> Select Input Clock for usb_pllclkin (Register: USBPLLCLKSEL)
|
||||
// <0=> IRC Oscillator
|
||||
// <1=> System Oscillator
|
||||
// <o13.0..4> M: PLL Multiplier Selection
|
||||
// <1-32><#-1>
|
||||
// <o13.5..6> P: PLL Divider Selection
|
||||
// <0=> 2
|
||||
// <1=> 4
|
||||
// <2=> 8
|
||||
// <3=> 16
|
||||
// <o13.7> DIRECT: Direct CCO Clock Output Enable
|
||||
// <o13.8> BYPASS: PLL Bypass Enable
|
||||
// </e11>
|
||||
// </e10>
|
||||
// <o14.0..7> System AHB Divider <0-255>
|
||||
// <i> 0 = is disabled
|
||||
// <o15.0> SYS Clock Enable
|
||||
// <o15.1> ROM Clock Enable
|
||||
// <o15.2> RAM Clock Enable
|
||||
// <o15.3> FLASH1 Clock Enable
|
||||
// <o15.4> FLASH2 Clock Enable
|
||||
// <o15.5> I2C Clock Enable
|
||||
// <o15.6> GPIO Clock Enable
|
||||
// <o15.7> CT16B0 Clock Enable
|
||||
// <o15.8> CT16B1 Clock Enable
|
||||
// <o15.9> CT32B0 Clock Enable
|
||||
// <o15.10> CT32B1 Clock Enable
|
||||
// <o15.11> SSP Clock Enable
|
||||
// <o15.12> UART Clock Enable
|
||||
// <o15.13> ADC Clock Enable
|
||||
// <o15.14> USB_REG Clock Enable
|
||||
// <o15.15> SWDT Clock Enable
|
||||
// <o15.16> IOCON Clock Enable
|
||||
// </e>
|
||||
*/
|
||||
#define CLOCK_SETUP 1
|
||||
#define SYSCLK_SETUP 1
|
||||
#define SYSOSC_SETUP 1
|
||||
#define SYSOSCCTRL_Val 0x00000000
|
||||
#define WDTOSC_SETUP 0
|
||||
#define WDTOSCCTRL_Val 0x000000A0
|
||||
#define SYSPLLCLKSEL_Val 0x00000001
|
||||
#define SYSPLL_SETUP 1
|
||||
#define SYSPLLCTRL_Val 0x00000025
|
||||
#define MAINCLKSEL_Val 0x00000003
|
||||
|
||||
// ******** Code Red *********
|
||||
// * Changed USBCLK_SETUP to 1
|
||||
// ***************************
|
||||
#define USBCLK_SETUP 1
|
||||
#define USBPLL_SETUP 1
|
||||
#define USBPLLCLKSEL_Val 0x00000001
|
||||
#define USBPLLCTRL_Val 0x00000003
|
||||
#define SYSAHBCLKDIV_Val 0x00000001
|
||||
#define AHBCLKCTRL_Val 0x0001005F
|
||||
|
||||
/*--------------------- Memory Mapping Configuration -------------------------
|
||||
//
|
||||
// <e> Memory Mapping
|
||||
// <o1.0..1> System Memory Remap (Register: SYSMEMREMAP)
|
||||
// <0=> Bootloader mapped to address 0
|
||||
// <1=> RAM mapped to address 0
|
||||
// <2=> Flash mapped to address 0
|
||||
// <3=> Flash mapped to address 0
|
||||
// </e>
|
||||
*/
|
||||
#define MEMMAP_SETUP 0
|
||||
#define SYSMEMREMAP_Val 0x00000001
|
||||
|
||||
/*
|
||||
//-------- <<< end of configuration section >>> ------------------------------
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Check the register settings
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define CHECK_RANGE(val, min, max) ((val < min) || (val > max))
|
||||
#define CHECK_RSVD(val, mask) (val & mask)
|
||||
|
||||
/* Clock Configuration -------------------------------------------------------*/
|
||||
#if (CHECK_RSVD((SYSOSCCTRL_Val), ~0x00000003))
|
||||
#error "SYSOSCCTRL: Invalid values of reserved bits!"
|
||||
#endif
|
||||
|
||||
#if (CHECK_RSVD((WDTOSCCTRL_Val), ~0x000001FF))
|
||||
#error "WDTOSCCTRL: Invalid values of reserved bits!"
|
||||
#endif
|
||||
|
||||
#if (CHECK_RANGE((SYSPLLCLKSEL_Val), 0, 2))
|
||||
#error "SYSPLLCLKSEL: Value out of range!"
|
||||
#endif
|
||||
|
||||
#if (CHECK_RSVD((SYSPLLCTRL_Val), ~0x000001FF))
|
||||
#error "SYSPLLCTRL: Invalid values of reserved bits!"
|
||||
#endif
|
||||
|
||||
#if (CHECK_RSVD((MAINCLKSEL_Val), ~0x00000003))
|
||||
#error "MAINCLKSEL: Invalid values of reserved bits!"
|
||||
#endif
|
||||
|
||||
#if (CHECK_RANGE((USBPLLCLKSEL_Val), 0, 1))
|
||||
#error "USBPLLCLKSEL: Value out of range!"
|
||||
#endif
|
||||
|
||||
#if (CHECK_RSVD((USBPLLCTRL_Val), ~0x000001FF))
|
||||
#error "USBPLLCTRL: Invalid values of reserved bits!"
|
||||
#endif
|
||||
|
||||
#if (CHECK_RSVD((USBPLLUEN_Val), ~0x00000001))
|
||||
#error "USBPLLUEN: Invalid values of reserved bits!"
|
||||
#endif
|
||||
|
||||
#if (CHECK_RANGE((SYSAHBCLKDIV_Val), 0, 255))
|
||||
#error "SYSAHBCLKDIV: Value out of range!"
|
||||
#endif
|
||||
|
||||
#if (CHECK_RSVD((AHBCLKCTRL_Val), ~0x0001FFFF))
|
||||
#error "AHBCLKCTRL: Invalid values of reserved bits!"
|
||||
#endif
|
||||
|
||||
#if (CHECK_RSVD((SYSMEMREMAP_Val), ~0x00000003))
|
||||
#error "SYSMEMREMAP: Invalid values of reserved bits!"
|
||||
#endif
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
DEFINES
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Define clocks
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define __XTAL (12000000UL) /* Oscillator frequency */
|
||||
#define __SYS_OSC_CLK ( __XTAL) /* Main oscillator frequency */
|
||||
#define __IRC_OSC_CLK (12000000UL) /* Internal RC oscillator frequency */
|
||||
|
||||
|
||||
#define __FREQSEL ((WDTOSCCTRL_Val >> 5) & 0x0F)
|
||||
#define __DIVSEL (((WDTOSCCTRL_Val & 0x1F) << 1) + 2)
|
||||
|
||||
#if (CLOCK_SETUP) /* Clock Setup */
|
||||
#if (SYSCLK_SETUP) /* System Clock Setup */
|
||||
#if (WDTOSC_SETUP) /* Watchdog Oscillator Setup*/
|
||||
#if (__FREQSEL == 0)
|
||||
#define __WDT_OSC_CLK ( 400000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 1)
|
||||
#define __WDT_OSC_CLK ( 500000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 2)
|
||||
#define __WDT_OSC_CLK ( 800000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 3)
|
||||
#define __WDT_OSC_CLK (1100000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 4)
|
||||
#define __WDT_OSC_CLK (1400000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 5)
|
||||
#define __WDT_OSC_CLK (1600000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 6)
|
||||
#define __WDT_OSC_CLK (1800000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 7)
|
||||
#define __WDT_OSC_CLK (2000000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 8)
|
||||
#define __WDT_OSC_CLK (2200000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 9)
|
||||
#define __WDT_OSC_CLK (2400000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 10)
|
||||
#define __WDT_OSC_CLK (2600000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 11)
|
||||
#define __WDT_OSC_CLK (2700000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 12)
|
||||
#define __WDT_OSC_CLK (2900000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 13)
|
||||
#define __WDT_OSC_CLK (3100000 / __DIVSEL)
|
||||
#elif (__FREQSEL == 14)
|
||||
#define __WDT_OSC_CLK (3200000 / __DIVSEL)
|
||||
#else
|
||||
#define __WDT_OSC_CLK (3400000 / __DIVSEL)
|
||||
#endif
|
||||
#else
|
||||
#define __WDT_OSC_CLK (1600000 / 2)
|
||||
#endif // WDTOSC_SETUP
|
||||
|
||||
/* sys_pllclkin calculation */
|
||||
#if ((SYSPLLCLKSEL_Val & 0x03) == 0)
|
||||
#define __SYS_PLLCLKIN (__IRC_OSC_CLK)
|
||||
#elif ((SYSPLLCLKSEL_Val & 0x03) == 1)
|
||||
#define __SYS_PLLCLKIN (__SYS_OSC_CLK)
|
||||
#elif ((SYSPLLCLKSEL_Val & 0x03) == 2)
|
||||
#define __SYS_PLLCLKIN (__WDT_OSC_CLK)
|
||||
#else
|
||||
#define __SYS_PLLCLKIN (0)
|
||||
#endif
|
||||
|
||||
#if (SYSPLL_SETUP) /* System PLL Setup */
|
||||
#define __SYS_PLLCLKOUT (__SYS_PLLCLKIN * ((SYSPLLCTRL_Val & 0x01F) + 1))
|
||||
#else
|
||||
#define __SYS_PLLCLKOUT (__SYS_PLLCLKIN * (1))
|
||||
#endif // SYSPLL_SETUP
|
||||
|
||||
/* main clock calculation */
|
||||
#if ((MAINCLKSEL_Val & 0x03) == 0)
|
||||
#define __MAIN_CLOCK (__IRC_OSC_CLK)
|
||||
#elif ((MAINCLKSEL_Val & 0x03) == 1)
|
||||
#define __MAIN_CLOCK (__SYS_PLLCLKIN)
|
||||
#elif ((MAINCLKSEL_Val & 0x03) == 2)
|
||||
#define __MAIN_CLOCK (__WDT_OSC_CLK)
|
||||
#elif ((MAINCLKSEL_Val & 0x03) == 3)
|
||||
#define __MAIN_CLOCK (__SYS_PLLCLKOUT)
|
||||
#else
|
||||
#define __MAIN_CLOCK (0)
|
||||
#endif
|
||||
|
||||
#define __SYSTEM_CLOCK (__MAIN_CLOCK / SYSAHBCLKDIV_Val)
|
||||
|
||||
#else // SYSCLK_SETUP
|
||||
#if (SYSAHBCLKDIV_Val == 0)
|
||||
#define __SYSTEM_CLOCK (0)
|
||||
#else
|
||||
#define __SYSTEM_CLOCK (__XTAL / SYSAHBCLKDIV_Val)
|
||||
#endif
|
||||
#endif // SYSCLK_SETUP
|
||||
|
||||
#else
|
||||
#define __SYSTEM_CLOCK (__XTAL)
|
||||
#endif // CLOCK_SETUP
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Clock Variable definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK;/*!< System Clock Frequency (Core Clock)*/
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Clock functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
void SystemCoreClockUpdate (void) /* Get Core Clock Frequency */
|
||||
{
|
||||
uint32_t wdt_osc = 0;
|
||||
|
||||
/* Determine clock frequency according to clock register values */
|
||||
switch ((LPC_SYSCON->WDTOSCCTRL >> 5) & 0x0F) {
|
||||
case 0: wdt_osc = 400000; break;
|
||||
case 1: wdt_osc = 500000; break;
|
||||
case 2: wdt_osc = 800000; break;
|
||||
case 3: wdt_osc = 1100000; break;
|
||||
case 4: wdt_osc = 1400000; break;
|
||||
case 5: wdt_osc = 1600000; break;
|
||||
case 6: wdt_osc = 1800000; break;
|
||||
case 7: wdt_osc = 2000000; break;
|
||||
case 8: wdt_osc = 2200000; break;
|
||||
case 9: wdt_osc = 2400000; break;
|
||||
case 10: wdt_osc = 2600000; break;
|
||||
case 11: wdt_osc = 2700000; break;
|
||||
case 12: wdt_osc = 2900000; break;
|
||||
case 13: wdt_osc = 3100000; break;
|
||||
case 14: wdt_osc = 3200000; break;
|
||||
case 15: wdt_osc = 3400000; break;
|
||||
}
|
||||
wdt_osc /= ((LPC_SYSCON->WDTOSCCTRL & 0x1F) << 1) + 2;
|
||||
|
||||
switch (LPC_SYSCON->MAINCLKSEL & 0x03) {
|
||||
case 0: /* Internal RC oscillator */
|
||||
SystemCoreClock = __IRC_OSC_CLK;
|
||||
break;
|
||||
case 1: /* Input Clock to System PLL */
|
||||
switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
|
||||
case 0: /* Internal RC oscillator */
|
||||
SystemCoreClock = __IRC_OSC_CLK;
|
||||
break;
|
||||
case 1: /* System oscillator */
|
||||
SystemCoreClock = __SYS_OSC_CLK;
|
||||
break;
|
||||
case 2: /* WDT Oscillator */
|
||||
SystemCoreClock = wdt_osc;
|
||||
break;
|
||||
case 3: /* Reserved */
|
||||
SystemCoreClock = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: /* WDT Oscillator */
|
||||
SystemCoreClock = wdt_osc;
|
||||
break;
|
||||
case 3: /* System PLL Clock Out */
|
||||
switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
|
||||
case 0: /* Internal RC oscillator */
|
||||
if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
|
||||
SystemCoreClock = __IRC_OSC_CLK;
|
||||
} else {
|
||||
SystemCoreClock = __IRC_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
|
||||
}
|
||||
break;
|
||||
case 1: /* System oscillator */
|
||||
if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
|
||||
SystemCoreClock = __SYS_OSC_CLK;
|
||||
} else {
|
||||
SystemCoreClock = __SYS_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
|
||||
}
|
||||
break;
|
||||
case 2: /* WDT Oscillator */
|
||||
if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
|
||||
SystemCoreClock = wdt_osc;
|
||||
} else {
|
||||
SystemCoreClock = wdt_osc * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
|
||||
}
|
||||
break;
|
||||
case 3: /* Reserved */
|
||||
SystemCoreClock = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
SystemCoreClock /= LPC_SYSCON->SYSAHBCLKDIV;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the system
|
||||
*
|
||||
* @param none
|
||||
* @return none
|
||||
*
|
||||
* @brief Setup the microcontroller system.
|
||||
* Initialize the System.
|
||||
*/
|
||||
void SystemInit (void)
|
||||
{
|
||||
#if (CLOCK_SETUP) /* Clock Setup */
|
||||
#if (SYSCLK_SETUP) /* System Clock Setup */
|
||||
#if (SYSOSC_SETUP) /* System Oscillator Setup */
|
||||
uint32_t i;
|
||||
|
||||
LPC_SYSCON->PDRUNCFG &= ~(1 << 5); /* Power-up System Osc */
|
||||
LPC_SYSCON->SYSOSCCTRL = SYSOSCCTRL_Val;
|
||||
for (i = 0; i < 200; i++) __NOP();
|
||||
LPC_SYSCON->SYSPLLCLKSEL = SYSPLLCLKSEL_Val; /* Select PLL Input */
|
||||
LPC_SYSCON->SYSPLLCLKUEN = 0x01; /* Update Clock Source */
|
||||
LPC_SYSCON->SYSPLLCLKUEN = 0x00; /* Toggle Update Register */
|
||||
LPC_SYSCON->SYSPLLCLKUEN = 0x01;
|
||||
while (!(LPC_SYSCON->SYSPLLCLKUEN & 0x01)); /* Wait Until Updated */
|
||||
#if (SYSPLL_SETUP) /* System PLL Setup */
|
||||
LPC_SYSCON->SYSPLLCTRL = SYSPLLCTRL_Val;
|
||||
LPC_SYSCON->PDRUNCFG &= ~(1 << 7); /* Power-up SYSPLL */
|
||||
while (!(LPC_SYSCON->SYSPLLSTAT & 0x01)); /* Wait Until PLL Locked */
|
||||
#endif
|
||||
#endif
|
||||
#if (WDTOSC_SETUP) /* Watchdog Oscillator Setup*/
|
||||
LPC_SYSCON->WDTOSCCTRL = WDTOSCCTRL_Val;
|
||||
LPC_SYSCON->PDRUNCFG &= ~(1 << 6); /* Power-up WDT Clock */
|
||||
#endif
|
||||
LPC_SYSCON->MAINCLKSEL = MAINCLKSEL_Val; /* Select PLL Clock Output */
|
||||
LPC_SYSCON->MAINCLKUEN = 0x01; /* Update MCLK Clock Source */
|
||||
LPC_SYSCON->MAINCLKUEN = 0x00; /* Toggle Update Register */
|
||||
LPC_SYSCON->MAINCLKUEN = 0x01;
|
||||
while (!(LPC_SYSCON->MAINCLKUEN & 0x01)); /* Wait Until Updated */
|
||||
#endif
|
||||
|
||||
#if (USBCLK_SETUP) /* USB Clock Setup */
|
||||
LPC_SYSCON->PDRUNCFG &= ~(1 << 10); /* Power-up USB PHY */
|
||||
#if (USBPLL_SETUP) /* USB PLL Setup */
|
||||
LPC_SYSCON->PDRUNCFG &= ~(1 << 8); /* Power-up USB PLL */
|
||||
LPC_SYSCON->USBPLLCLKSEL = USBPLLCLKSEL_Val; /* Select PLL Input */
|
||||
LPC_SYSCON->USBPLLCLKUEN = 0x01; /* Update Clock Source */
|
||||
LPC_SYSCON->USBPLLCLKUEN = 0x00; /* Toggle Update Register */
|
||||
LPC_SYSCON->USBPLLCLKUEN = 0x01;
|
||||
while (!(LPC_SYSCON->USBPLLCLKUEN & 0x01)); /* Wait Until Updated */
|
||||
LPC_SYSCON->USBPLLCTRL = USBPLLCTRL_Val;
|
||||
while (!(LPC_SYSCON->USBPLLSTAT & 0x01)); /* Wait Until PLL Locked */
|
||||
LPC_SYSCON->USBCLKSEL = 0x00; /* Select USB PLL */
|
||||
#else
|
||||
LPC_SYSCON->USBCLKSEL = 0x01; /* Select Main Clock */
|
||||
#endif
|
||||
#else
|
||||
LPC_SYSCON->PDRUNCFG |= (1 << 10); /* Power-down USB PHY */
|
||||
LPC_SYSCON->PDRUNCFG |= (1 << 8); /* Power-down USB PLL */
|
||||
#endif
|
||||
|
||||
LPC_SYSCON->SYSAHBCLKDIV = SYSAHBCLKDIV_Val;
|
||||
LPC_SYSCON->SYSAHBCLKCTRL = AHBCLKCTRL_Val;
|
||||
#endif
|
||||
|
||||
|
||||
#if (MEMMAP_SETUP || MEMMAP_INIT) /* Memory Mapping Setup */
|
||||
LPC_SYSCON->SYSMEMREMAP = SYSMEMREMAP_Val;
|
||||
#endif
|
||||
}
|
153
firmware/src/usbcomp.c
Normal file
153
firmware/src/usbcomp.c
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*----------------------------------------------------------------------------
|
||||
* Name: vcomdemo.c
|
||||
* Purpose: USB virtual COM port Demo
|
||||
* Version: V1.02
|
||||
*----------------------------------------------------------------------------
|
||||
* 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.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "LPC13xx.h"
|
||||
#include "type.h"
|
||||
|
||||
#include "usb.h"
|
||||
#include "usbcfg.h"
|
||||
#include "usbhw.h"
|
||||
#include "usbcore.h"
|
||||
#include "cdc.h"
|
||||
#include "cdcuser.h"
|
||||
#include "serial.h"
|
||||
#include "vcomdemo.h"
|
||||
#include "mscuser.h"
|
||||
#include "memory.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
|
||||
|
||||
#include "edubrm.h"
|
||||
|
||||
extern uint8_t Memory[MSC_MemorySize]; /* MSC Memory in RAM */
|
||||
|
||||
#define EN_TIMER32_1 (1<<10)
|
||||
#define EN_IOCON (1<<16)
|
||||
#define EN_USBREG (1<<14)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Initializes the VCOM port.
|
||||
Call this function before using VCOM_putchar or VCOM_getchar
|
||||
*---------------------------------------------------------------------------*/
|
||||
void VCOM_Init(void) {
|
||||
|
||||
CDC_Init ();
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Reads character from serial port buffer and writes to USB buffer
|
||||
*---------------------------------------------------------------------------*/
|
||||
void VCOM_Serial2Usb(void) {
|
||||
static char serBuf [USB_CDC_BUFSIZE];
|
||||
int numBytesRead, numAvailByte;
|
||||
|
||||
ser_AvailChar (&numAvailByte);
|
||||
if (numAvailByte > 0) {
|
||||
if (CDC_DepInEmpty) {
|
||||
numBytesRead = ser_Read (&serBuf[0], &numAvailByte);
|
||||
|
||||
CDC_DepInEmpty = 0;
|
||||
USB_WriteEP (CDC_DEP_IN, (unsigned char *)&serBuf[0], numBytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Reads character from USB buffer and writes to serial port buffer
|
||||
*---------------------------------------------------------------------------*/
|
||||
void VCOM_Usb2Serial(void) {
|
||||
static char serBuf [32];
|
||||
int numBytesToRead, numBytesRead, numAvailByte;
|
||||
|
||||
CDC_OutBufAvailChar (&numAvailByte);
|
||||
if (numAvailByte > 0) {
|
||||
numBytesToRead = numAvailByte > 32 ? 32 : numAvailByte;
|
||||
numBytesRead = CDC_RdOutBuf (&serBuf[0], &numBytesToRead);
|
||||
ser_Write (&serBuf[0], &numBytesRead);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Reads character from USB buffer and writes to serial port buffer
|
||||
*---------------------------------------------------------------------------*/
|
||||
void VCOM_Usb2SerialTest(void) {
|
||||
static char serBuf [32];
|
||||
int numBytesRead;
|
||||
|
||||
strcpy(serBuf,"Test\n");
|
||||
numBytesRead = strlen(serBuf);
|
||||
ser_Write (&serBuf[0], &numBytesRead);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
checks the serial state and initiates notification
|
||||
*---------------------------------------------------------------------------*/
|
||||
void VCOM_CheckSerialState (void) {
|
||||
unsigned short temp;
|
||||
static unsigned short serialState;
|
||||
|
||||
temp = CDC_GetSerialState();
|
||||
if (serialState != temp) {
|
||||
serialState = temp;
|
||||
CDC_NotificationIn(); // send SERIAL_STATE notification
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Main Program
|
||||
*---------------------------------------------------------------------------*/
|
||||
int main (void) {
|
||||
uint32_t n;
|
||||
|
||||
for (n = 0; n < MSC_ImageSize; n++) { /* Copy Initial Disk Image */
|
||||
Memory[n] = DiskImage[n]; /* from Flash to RAM */
|
||||
}
|
||||
|
||||
/* Basic chip initialization is taken care of in SystemInit() called
|
||||
* from the startup code. SystemInit() and chip settings are defined
|
||||
* in the CMSIS system_<part family>.c file.
|
||||
*/
|
||||
|
||||
/* Enable Timer32_1, IOCON, and USB blocks */
|
||||
LPC_SYSCON->SYSAHBCLKCTRL |= (EN_TIMER32_1 | EN_IOCON | EN_USBREG);
|
||||
|
||||
USBIOClkConfig();
|
||||
|
||||
VCOM_Init(); // VCOM Initialization
|
||||
|
||||
USB_Init(); // USB Initialization
|
||||
USB_Connect(TRUE); // USB Connect
|
||||
|
||||
while (!USB_Configuration) ; // wait until USB is configured
|
||||
|
||||
//VCOM_Usb2SerialTest();
|
||||
|
||||
enableLED();
|
||||
|
||||
while (1) { // Loop forever
|
||||
VCOM_Brm2Usb();
|
||||
VCOM_CheckSerialState();
|
||||
VCOM_Usb2Brm();
|
||||
} // end while
|
||||
} // end main ()
|
||||
|
||||
|
1085
firmware/src/usbcore.c
Normal file
1085
firmware/src/usbcore.c
Normal file
File diff suppressed because it is too large
Load diff
279
firmware/src/usbdesc.c
Normal file
279
firmware/src/usbdesc.c
Normal file
|
@ -0,0 +1,279 @@
|
|||
/*----------------------------------------------------------------------------
|
||||
* 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
|
||||
*---------------------------------------------------------------------------*/
|
||||
#include "type.h"
|
||||
|
||||
#include "usb.h"
|
||||
#include "cdc.h"
|
||||
#include "usbcfg.h"
|
||||
#include "usbdesc.h"
|
||||
|
||||
#include "msc.h"
|
||||
#include "config.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 */
|
||||
0x02, /* bDeviceSubClass */
|
||||
0x01, /* bDeviceProtocol */
|
||||
USB_MAX_PACKET0, /* bMaxPacketSize0 */
|
||||
|
||||
// 0x70, 0x08, /* idVendorL */ //this vendor code is here in order to bypase linux probing for ttyACM0
|
||||
// 0x01, 0x00, /* idProductL */ //this product code is here in order to bypase linux probing for ttyACM0
|
||||
|
||||
WBVAL(USB_VENDOR_ID), /* idVendor */
|
||||
WBVAL(USB_PROD_ID), /* idProduct */
|
||||
WBVAL(USB_DEVICE), /* 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 +
|
||||
1*USB_INTERFACE_DESC_SIZE + /* mass storage interface */
|
||||
2*USB_ENDPOINT_DESC_SIZE + /* bulk endpoints */
|
||||
1*USB_INTERFACE_ASSOCIATION_DESC_SIZE + /* interface association */
|
||||
1*USB_INTERFACE_DESC_SIZE + /* communication interface */
|
||||
0x0013 + /* CDC functions */
|
||||
1*USB_ENDPOINT_DESC_SIZE + /* interrupt endpoint */
|
||||
1*USB_INTERFACE_DESC_SIZE + /* data interface */
|
||||
2*USB_ENDPOINT_DESC_SIZE + /* bulk endpoints */
|
||||
0
|
||||
),
|
||||
|
||||
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_REMOTE_WAKEUP*/,
|
||||
USB_CONFIG_POWER_MA(100), /* bMaxPower, device power consumption is 100 mA */
|
||||
|
||||
/* Interface 0, Alternate Setting 0, MSC Class */
|
||||
USB_INTERFACE_DESC_SIZE, /* bLength */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
USB_MSC_IF_NUM, /* bInterfaceNumber */
|
||||
0x00, /* bAlternateSetting */
|
||||
0x02, /* bNumEndpoints */
|
||||
USB_DEVICE_CLASS_STORAGE, /* bInterfaceClass */
|
||||
MSC_SUBCLASS_SCSI, /* bInterfaceSubClass */
|
||||
MSC_PROTOCOL_BULK_ONLY, /* bInterfaceProtocol */
|
||||
0x04, /* iInterface */
|
||||
|
||||
/* 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(0x0040), /* wMaxPacketSize */
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
|
||||
/* 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(0x0040), /* wMaxPacketSize */
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
|
||||
/* IAD to associate the two CDC interfaces */
|
||||
USB_INTERFACE_ASSOCIATION_DESC_SIZE, /* bLength */
|
||||
USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
USB_CDC_CIF_NUM, /* bFirstInterface */
|
||||
2, /* bInterfaceCount */
|
||||
CDC_COMMUNICATION_INTERFACE_CLASS, /* bFunctionClass */
|
||||
CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */
|
||||
0, /* bFunctionProtocol */
|
||||
0x06, /* iFunction (Index of string descriptor describing this 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 */
|
||||
0x05, /* 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 */
|
||||
0x01, /* bmCapabilities: device handles call management */
|
||||
USB_CDC_DIF_NUM, /* 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 */
|
||||
0x02, /* 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 */
|
||||
0x02, /* 2ms */ /* 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 */
|
||||
0x05, /* iInterface: */
|
||||
/* Endpoint, EP3 Bulk Out */
|
||||
USB_ENDPOINT_DESC_SIZE, /* bLength */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
USB_ENDPOINT_OUT(3), /* bEndpointAddress */
|
||||
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */
|
||||
WBVAL(USB_CDC_BUFSIZE), /* wMaxPacketSize */
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
/* Endpoint, EP3 Bulk In */
|
||||
USB_ENDPOINT_DESC_SIZE, /* bLength */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
USB_ENDPOINT_IN(3), /* bEndpointAddress */
|
||||
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */
|
||||
WBVAL(USB_CDC_BUFSIZE), /* wMaxPacketSize */
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
|
||||
/* 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 + lenght) */
|
||||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
'N',0,
|
||||
'X',0,
|
||||
'P',0,
|
||||
' ',0,
|
||||
'S',0,
|
||||
'E',0,
|
||||
'M',0,
|
||||
'I',0,
|
||||
'C',0,
|
||||
'O',0,
|
||||
'N',0,
|
||||
'D',0,
|
||||
' ',0,
|
||||
/* Index 0x02: Product */
|
||||
(21*2 + 2), /* bLength ( 21 Char + Type + lenght) */
|
||||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
'N',0,
|
||||
'X',0,
|
||||
'P',0,
|
||||
' ',0,
|
||||
'L',0,
|
||||
'P',0,
|
||||
'C',0,
|
||||
'1',0,
|
||||
'3',0,
|
||||
'x',0,
|
||||
'x',0,
|
||||
' ',0,
|
||||
'M',0,
|
||||
'S',0,
|
||||
'D',0,
|
||||
'/',0,
|
||||
'V',0,
|
||||
'C',0,
|
||||
'O',0,
|
||||
'M',0,
|
||||
' ',0,
|
||||
/* Index 0x03: Serial Number */
|
||||
(16*2 + 2), /* bLength (12 Char + Type + lenght) */
|
||||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
'C',0,
|
||||
'O',0,
|
||||
'M',0,
|
||||
'P',0,
|
||||
'O',0,
|
||||
'S',0,
|
||||
'I',0,
|
||||
'T',0,
|
||||
'E',0,
|
||||
' ',0,
|
||||
'D',0,
|
||||
'E',0,
|
||||
'M',0,
|
||||
'O',0,
|
||||
' ',0,
|
||||
' ',0,
|
||||
/* Index 0x04: Interface 0, Alternate Setting 0 */
|
||||
( 6*2 + 2), /* bLength (6 Char + Type + lenght) */
|
||||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
'M',0,
|
||||
'e',0,
|
||||
'm',0,
|
||||
'o',0,
|
||||
'r',0,
|
||||
'y',0,
|
||||
/* Index 0x05: Interface 0, Alternate Setting 0 */
|
||||
( 4*2 + 2), /* bLength (4 Char + Type + lenght) */
|
||||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
'V',0,
|
||||
'C',0,
|
||||
'O',0,
|
||||
'M',0,
|
||||
/* Index 0x05: Interface 0, Alternate Setting 0 */
|
||||
( 8*2 + 2), /* bLength (4 Char + Type + lenght) */
|
||||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
'C',0,
|
||||
'O',0,
|
||||
'M',0,
|
||||
'/',0,
|
||||
'D',0,
|
||||
'A',0,
|
||||
'T',0,
|
||||
'A',0,
|
||||
};
|
552
firmware/src/usbhw.c
Normal file
552
firmware/src/usbhw.c
Normal file
|
@ -0,0 +1,552 @@
|
|||
/*----------------------------------------------------------------------------
|
||||
* U S B - K e r n e l
|
||||
*----------------------------------------------------------------------------
|
||||
* Name: usbhw.c
|
||||
* Purpose: USB Hardware Layer Module for Philips LPC17xx
|
||||
* 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 Added USB_ClearEPBuf
|
||||
* V1.00 Initial Version
|
||||
*----------------------------------------------------------------------------*/
|
||||
#include "LPC13xx.h" /* LPC13xx definitions */
|
||||
#include "usb.h"
|
||||
#include "usbcfg.h"
|
||||
#include "usbreg.h"
|
||||
#include "usbhw.h"
|
||||
#include "usbcore.h"
|
||||
#include "usbuser.h"
|
||||
|
||||
|
||||
/*
|
||||
* USB and IO Clock configuration only.
|
||||
* The same as call PeriClkIOInit(IOCON_USB);
|
||||
* The purpose is to reduce the code space for
|
||||
* overall USB project and reserve code space for
|
||||
* USB debugging.
|
||||
* Parameters: None
|
||||
* Return Value: None
|
||||
*/
|
||||
void USBIOClkConfig( void )
|
||||
{
|
||||
/* Enable AHB clock to the GPIO domain. */
|
||||
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
|
||||
|
||||
LPC_IOCON->PIO0_1 &= ~0x07;
|
||||
LPC_IOCON->PIO0_1 |= 0x01; /* CLK OUT */
|
||||
|
||||
/* Enable AHB clock to the USB block. */
|
||||
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<14);
|
||||
LPC_IOCON->PIO0_3 &= ~0x1F;
|
||||
LPC_IOCON->PIO0_3 |= 0x01; /* Secondary function VBUS */
|
||||
LPC_IOCON->PIO0_6 &= ~0x07;
|
||||
LPC_IOCON->PIO0_6 |= 0x01; /* Secondary function SoftConn */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delay number of clock cycles
|
||||
* Parameters: Delay length
|
||||
* Return Value: None
|
||||
*/
|
||||
|
||||
void delay (uint32_t length ) {
|
||||
uint32_t i;
|
||||
|
||||
for ( i = 0; i < length; i++ );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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->DevIntClr = CCEMTY_INT;
|
||||
LPC_USB->CmdCode = cmd;
|
||||
while ((LPC_USB->DevIntSt & (CCEMTY_INT | DEV_STAT_INT)) == 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write Command Data
|
||||
* Parameters: cmd: Command
|
||||
* val: Data
|
||||
* Return Value: None
|
||||
*/
|
||||
|
||||
void WrCmdDat (uint32_t cmd, uint32_t val) {
|
||||
|
||||
WrCmd(cmd);
|
||||
WrCmd(val);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write Command to Endpoint
|
||||
* Parameters: cmd: Command
|
||||
* val: Data
|
||||
* Return Value: None
|
||||
*/
|
||||
|
||||
void WrCmdEP (uint32_t EPNum, uint32_t cmd){
|
||||
|
||||
WrCmd(CMD_SEL_EP(EPAdr(EPNum)));
|
||||
WrCmd(cmd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read Command Data
|
||||
* Parameters: cmd: Command
|
||||
* Return Value: Data Value
|
||||
*/
|
||||
|
||||
uint32_t RdCmdDat (uint32_t cmd) {
|
||||
|
||||
LPC_USB->DevIntClr = CCEMTY_INT | CDFULL_INT;
|
||||
LPC_USB->CmdCode = cmd;
|
||||
while ((LPC_USB->DevIntSt & (CDFULL_INT | DEV_STAT_INT)) == 0);
|
||||
return (LPC_USB->CmdData);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* USB Initialize Function
|
||||
* Called by the User to initialize USB
|
||||
* Return Value: None
|
||||
*/
|
||||
|
||||
void USB_Init (void) {
|
||||
|
||||
#if USB_FIQ_EVENT
|
||||
/* It's important that only BULK and FRAME(ISO) can be routed
|
||||
to FIQ. */
|
||||
LPC_USB->DevFIQSel = 0x01; /* SOF Use FIQ */
|
||||
|
||||
/* Enable the USB Interrupt */
|
||||
NVIC_EnableIRQ(USB_FIQn);
|
||||
#endif
|
||||
|
||||
/* Enable the USB Interrupt */
|
||||
NVIC_EnableIRQ(USB_IRQn);
|
||||
|
||||
USB_Reset();
|
||||
USB_SetAddress(0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
|
||||
LPC_USB->DevIntClr = 0x000FFFFF;
|
||||
/* Enable all eight(8) EPs, note: EP won't be ready until it's
|
||||
configured/enabled when device sending SetEPStatus command
|
||||
to the command engine. */
|
||||
LPC_USB->DevIntEn = DEV_STAT_INT | (0xFF<<1) |
|
||||
(USB_SOF_EVENT ? FRAME_INT : 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
cfg = 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));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Configure USB Endpoint according to Descriptor
|
||||
* Parameters: pEPD: Pointer to Endpoint Descriptor
|
||||
* Return Value: None
|
||||
*/
|
||||
|
||||
void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set Direction for USB Control Endpoint
|
||||
* Parameters: dir: Out (dir == 0), In (dir <> 0)
|
||||
* Return Value: None
|
||||
*/
|
||||
|
||||
void USB_DirCtrlEP (uint32_t dir) {
|
||||
dir = 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->Ctrl = ((EPNum & 0x0F) << 2) | CTRL_RD_EN;
|
||||
/* 3 clock cycles to fetch the packet length from RAM. */
|
||||
delay( 5 );
|
||||
|
||||
do {
|
||||
cnt = LPC_USB->RxPLen;
|
||||
} while ((cnt & PKT_DV) == 0);
|
||||
cnt &= PKT_LNGTH_MASK;
|
||||
|
||||
for (n = 0; n < (cnt + 3) / 4; n++) {
|
||||
*((uint32_t __attribute__((packed)) *)pData) = LPC_USB->RxData;
|
||||
pData += 4;
|
||||
}
|
||||
|
||||
LPC_USB->Ctrl = 0;
|
||||
|
||||
if ((EPNum & 0x80) != 0x04) { /* 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->Ctrl = ((EPNum & 0x0F) << 2) | CTRL_WR_EN;
|
||||
/* 3 clock cycles to fetch the packet length from RAM. */
|
||||
delay( 5 );
|
||||
LPC_USB->TxPLen = cnt;
|
||||
|
||||
for (n = 0; n < (cnt + 3) / 4; n++) {
|
||||
LPC_USB->TxData = *((uint32_t __attribute__((packed)) *)pData);
|
||||
pData += 4;
|
||||
}
|
||||
|
||||
LPC_USB->Ctrl = 0;
|
||||
|
||||
WrCmdEP(EPNum, CMD_VALID_BUF);
|
||||
|
||||
return (cnt);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
disr = LPC_USB->DevIntSt; /* Device Interrupt Status */
|
||||
LPC_USB->DevIntClr = disr;
|
||||
|
||||
/* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
|
||||
if (disr & 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->DevIntClr = FRAME_INT;
|
||||
USB_SOF_Event();
|
||||
SOFIRQCount++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USB_ERROR_EVENT
|
||||
/* NO error interrupt anymore, below code can be used
|
||||
as example to get error status from command engine. */
|
||||
/* Error Interrupt */
|
||||
if (disr & ERR_INT) {
|
||||
WrCmd(CMD_RD_ERR_STAT);
|
||||
val = RdCmdDat(DAT_RD_ERR_STAT);
|
||||
USB_Error_Event(val);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Endpoint's Interrupt */
|
||||
if (disr & (0xFF<<1)) {
|
||||
/* if any of the EP0 through EP7 is set, or bit 1 through 9 on disr */
|
||||
for (n = 0; n < USB_EP_NUM; n++) { /* Check All Endpoints */
|
||||
/* skip frame interrupt at bit 0 in disr */
|
||||
// if (disr & ((1 << n)<<1)) {
|
||||
if ((disr>>1) & (1 << n)) {
|
||||
m = n >> 1;
|
||||
/* clear EP interrupt by sending cmd to the command engine. */
|
||||
WrCmd(CMD_SEL_EP_CLRI(n));
|
||||
val = RdCmdDat(DAT_SEL_EP_CLRI(n));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
isr_end:
|
||||
return;
|
||||
}
|
217
firmware/src/usbuser.c
Normal file
217
firmware/src/usbuser.c
Normal file
|
@ -0,0 +1,217 @@
|
|||
/*----------------------------------------------------------------------------
|
||||
* 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 microcontroller devices only. Nothing else
|
||||
* gives you the right to use this software.
|
||||
*
|
||||
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||
*---------------------------------------------------------------------------*/
|
||||
#include "type.h"
|
||||
|
||||
#include "usb.h"
|
||||
#include "usbcfg.h"
|
||||
#include "usbhw.h"
|
||||
#include "usbcore.h"
|
||||
#include "usbuser.h"
|
||||
#include "cdcuser.h"
|
||||
#include "mscuser.h"
|
||||
#include "memory.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 : NULL)
|
||||
|
||||
/* USB Endpoint Events Callback Pointers */
|
||||
void (* const USB_P_EP[USB_LOGIC_EP_NUM]) (uint32_t event) = {
|
||||
P_EP(0),
|
||||
P_EP(1),
|
||||
P_EP(2),
|
||||
P_EP(3),
|
||||
P_EP(4),
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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:
|
||||
MSC_BulkOut();
|
||||
break;
|
||||
case USB_EVT_IN:
|
||||
MSC_BulkIn();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* USB Endpoint 3 Event Callback
|
||||
* Called automatically on USB Endpoint 3 Event
|
||||
* Parameter: event
|
||||
*/
|
||||
|
||||
void USB_EndPoint3 (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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue