Version 2.4 - 15th September 2018

Adds support for Adafruit's ATSAMD51-based M4 boards.
This commit is contained in:
David Johnson-Davies 2018-09-15 14:58:29 +01:00 committed by GitHub
parent b1c62bc728
commit 958fd2184c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 231 additions and 37 deletions

View File

@ -1,5 +1,5 @@
/* uLisp ARM Version 2.3 - www.ulisp.com
David Johnson-Davies - www.technoblogy.com - 2nd June 2018
/* uLisp ARM Version 2.4 - www.ulisp.com
David Johnson-Davies - www.technoblogy.com - 15th September 2018
Licensed under the MIT license: https://opensource.org/licenses/MIT
*/
@ -23,6 +23,9 @@
#if defined(sdcardsupport)
#include <SD.h>
#define SDSIZE 172
#else
#define SDSIZE 0
#endif
// C Macros
@ -116,22 +119,40 @@ typedef void (*pfun_t)(char);
#define BUFFERSIZE 34 // Number of bits+2
#if defined(ARDUINO_SAMD_ZERO)
#define WORKSPACESIZE 3072 /* Cells (8*bytes) */
#define WORKSPACESIZE 3072-SDSIZE /* Cells (8*bytes) */
#define SYMBOLTABLESIZE 512 /* Bytes */
#define SDCARD_SS_PIN 10
uint8_t _end;
#elif defined(ARDUINO_SAM_DUE)
#define WORKSPACESIZE 10240 /* Cells (8*bytes) */
#define WORKSPACESIZE 3072-SDSIZE /* Cells (8*bytes) */
#define SYMBOLTABLESIZE 512 /* Bytes */
#define SDCARD_SS_PIN 10
extern uint8_t _end;
#elif defined(ARDUINO_SAMD_MKRZERO)
#define WORKSPACESIZE 3072 /* Cells (8*bytes) */
#define WORKSPACESIZE 3072-SDSIZE /* Cells (8*bytes) */
#define SYMBOLTABLESIZE 512 /* Bytes */
uint8_t _end;
#elif defined(ARDUINO_METRO_M4)
#define WORKSPACESIZE 3072-SDSIZE /* Cells (8*bytes) */
#define FLASHSIZE 65536 /* Bytes */
#define SYMBOLTABLESIZE 1024 /* Bytes */
uint8_t _end;
#elif defined(ARDUINO_ITSYBITSY_M4)
#define WORKSPACESIZE 3072-SDSIZE /* Cells (8*bytes) */
#define FLASHSIZE 65536 /* Bytes */
#define SYMBOLTABLESIZE 1024 /* Bytes */
uint8_t _end;
#elif defined(ARDUINO_FEATHER_M4)
#define WORKSPACESIZE 3072-SDSIZE /* Cells (8*bytes) */
#define FLASHSIZE 65536 /* Bytes */
#define SYMBOLTABLESIZE 1024 /* Bytes */
uint8_t _end;
#elif defined(_VARIANT_BBC_MICROBIT_)
#define WORKSPACESIZE 1024 /* Cells (8*bytes) */
#define SYMBOLTABLESIZE 512 /* Bytes */
@ -373,14 +394,115 @@ char *MakeFilename (object *arg) {
// Save-image and load-image
#if defined(sdcardsupport)
void SDWriteInt(File file, int data) {
file.write(data & 0xFF); file.write(data>>8 & 0xFF);
}
void SDWritePtr(File file, uintptr_t data) {
void SDWriteInt (File file, int data) {
file.write(data & 0xFF); file.write(data>>8 & 0xFF);
file.write(data>>16 & 0xFF); file.write(data>>24 & 0xFF);
}
#elif defined(ARDUINO_METRO_M4) || defined(ARDUINO_ITSYBITSY_M4) || defined(ARDUINO_FEATHER_M4)
// Winbond DataFlash support for Adafruit M4 Express boards
#define PAGEPROG 0x02
#define READSTATUS 0x05
#define READDATA 0x03
#define WRITEENABLE 0x06
#define BLOCK64K 0xD8
#define READID 0x90
// Arduino pins used for dataflash
#if defined(ARDUINO_ITSYBITSY_M4)
const int sck = 32, ssel = 33, mosi = 34, miso = 35;
#elif defined(ARDUINO_METRO_M4)
const int sck = 41, ssel = 42, mosi = 43, miso = 44;
#elif defined(ARDUINO_FEATHER_M4)
const int sck = 34, ssel = 35, mosi = 36, miso = 37;
#endif
boolean FlashSetup () {
uint8_t manID, devID;
digitalWrite(ssel, HIGH); pinMode(ssel, OUTPUT);
pinMode(sck, OUTPUT);
pinMode(mosi, OUTPUT);
pinMode(miso, INPUT);
digitalWrite(sck, LOW); digitalWrite(mosi, HIGH);
digitalWrite(ssel, LOW);
FlashWrite(READID);
for(uint8_t i=0; i<4; i++) manID = FlashRead();
devID = FlashRead();
digitalWrite(ssel, HIGH);
return (devID == 0x14); // Found correct device
}
inline void FlashWrite (uint8_t data) {
shiftOut(mosi, sck, MSBFIRST, data);
}
void FlashBusy () {
digitalWrite(ssel, 0);
FlashWrite(READSTATUS);
while (FlashRead() & 1 != 0);
digitalWrite(ssel, 1);
}
void FlashWriteEnable () {
digitalWrite(ssel, 0);
FlashWrite(WRITEENABLE);
digitalWrite(ssel, 1);
}
void FlashBeginRead () {
FlashBusy();
digitalWrite(ssel, 0);
FlashWrite(READDATA);
FlashWrite(0); FlashWrite(0); FlashWrite(0);
}
inline uint8_t FlashRead () {
int data;
return shiftIn(miso, sck, MSBFIRST);
}
inline void FlashEndRead(void) {
digitalWrite(ssel, 1);
}
void FlashBeginWrite () {
FlashBusy();
// Erase 64K
FlashWriteEnable();
digitalWrite(ssel, 0);
FlashWrite(BLOCK64K);
FlashWrite(0); FlashWrite(0); FlashWrite(0);
digitalWrite(ssel, 1);
FlashBusy();
}
inline uint8_t FlashReadByte () {
return FlashRead();
}
void FlashWriteByte (unsigned int *addr, uint8_t data) {
// New page
if (((*addr) & 0xFF) == 0) {
digitalWrite(ssel, 1);
FlashBusy();
FlashWriteEnable();
digitalWrite(ssel, 0);
FlashWrite(PAGEPROG);
FlashWrite((*addr)>>16);
FlashWrite((*addr)>>8);
FlashWrite(0);
}
FlashWrite(data);
(*addr)++;
}
inline void FlashEndWrite (void) {
digitalWrite(ssel, 1);
}
void FlashWriteInt (unsigned int *addr, int data) {
FlashWriteByte(addr, data & 0xFF); FlashWriteByte(addr, data>>8 & 0xFF);
FlashWriteByte(addr, data>>16 & 0xFF); FlashWriteByte(addr, data>>24 & 0xFF);
}
#endif
int saveimage (object *arg) {
@ -393,21 +515,49 @@ int saveimage (object *arg) {
} else file = SD.open("ULISP.IMG", O_RDWR | O_CREAT | O_TRUNC);
if (!file) error(PSTR("Problem saving to SD card"));
unsigned int imagesize = compactimage(&arg);
SDWritePtr(file, (uintptr_t)arg);
SDWriteInt(file, (uintptr_t)arg);
SDWriteInt(file, imagesize);
SDWritePtr(file, (uintptr_t)GlobalEnv);
SDWritePtr(file, (uintptr_t)GCStack);
SDWriteInt(file, (uintptr_t)GlobalEnv);
SDWriteInt(file, (uintptr_t)GCStack);
#if SYMBOLTABLESIZE > BUFFERSIZE
SDWritePtr(file, (uintptr_t)SymbolTop);
SDWriteInt(file, (uintptr_t)SymbolTop);
for (int i=0; i<SYMBOLTABLESIZE; i++) file.write(SymbolTable[i]);
#endif
for (unsigned int i=0; i<imagesize; i++) {
object *obj = &Workspace[i];
SDWritePtr(file, (uintptr_t)car(obj));
SDWritePtr(file, (uintptr_t)cdr(obj));
SDWriteInt(file, (uintptr_t)car(obj));
SDWriteInt(file, (uintptr_t)cdr(obj));
}
file.close();
return imagesize;
#elif defined(ARDUINO_METRO_M4) || defined(ARDUINO_ITSYBITSY_M4) || defined(ARDUINO_FEATHER_M4)
unsigned int imagesize = compactimage(&arg);
if (!FlashSetup()) error(PSTR("No DataFlash found."));
// Save to DataFlash
int bytesneeded = imagesize*8 + SYMBOLTABLESIZE + 20;
if (bytesneeded > FLASHSIZE) {
pfstring(PSTR("Error: Image size too large: "), pserial);
pint(imagesize, pserial); pln(pserial);
GCStack = NULL;
longjmp(exception, 1);
}
unsigned int addr = 0;
FlashBeginWrite();
FlashWriteInt(&addr, (uintptr_t)arg);
FlashWriteInt(&addr, imagesize);
FlashWriteInt(&addr, (uintptr_t)GlobalEnv);
FlashWriteInt(&addr, (uintptr_t)GCStack);
#if SYMBOLTABLESIZE > BUFFERSIZE
FlashWriteInt(&addr, (uintptr_t)SymbolTop);
for (int i=0; i<SYMBOLTABLESIZE; i++) FlashWriteByte(&addr, SymbolTable[i]);
#endif
for (unsigned int i=0; i<imagesize; i++) {
object *obj = &Workspace[i];
FlashWriteInt(&addr, (uintptr_t)car(obj));
FlashWriteInt(&addr, (uintptr_t)cdr(obj));
}
FlashEndWrite();
return imagesize;
#else
(void) arg;
error(PSTR("save-image not available"));
@ -416,15 +566,16 @@ int saveimage (object *arg) {
}
#if defined(sdcardsupport)
unsigned int SDReadInt (File file) {
int lo = file.read(); int hi = file.read();
return lo | hi<<8;
}
object *SDReadPtr (File file) {
int SDReadInt (File file) {
uintptr_t b0 = file.read(); uintptr_t b1 = file.read();
uintptr_t b2 = file.read(); uintptr_t b3 = file.read();
return (object *)(b0 | b1<<8 | b2<<16 | b3<<24);
return b0 | b1<<8 | b2<<16 | b3<<24;
}
#elif defined(ARDUINO_METRO_M4) || defined(ARDUINO_ITSYBITSY_M4) || defined(ARDUINO_FEATHER_M4)
int FlashReadInt () {
uint8_t b0 = FlashReadByte(); uint8_t b1 = FlashReadByte();
uint8_t b2 = FlashReadByte(); uint8_t b3 = FlashReadByte();
return b0 | b1<<8 | b2<<16 | b3<<24;
}
#endif
@ -435,22 +586,42 @@ int loadimage (object *filename) {
if (stringp(filename)) file = SD.open(MakeFilename(filename));
else file = SD.open("ULISP.IMG");
if (!file) error(PSTR("Problem loading from SD card"));
SDReadPtr(file);
SDReadInt(file);
int imagesize = SDReadInt(file);
GlobalEnv = SDReadPtr(file);
GCStack = SDReadPtr(file);
GlobalEnv = (object *)SDReadInt(file);
GCStack = (object *)SDReadInt(file);
#if SYMBOLTABLESIZE > BUFFERSIZE
SymbolTop = (char *)SDReadPtr(file);
SymbolTop = (char *)SDReadInt(file);
for (int i=0; i<SYMBOLTABLESIZE; i++) SymbolTable[i] = file.read();
#endif
for (int i=0; i<imagesize; i++) {
object *obj = &Workspace[i];
car(obj) = SDReadPtr(file);
cdr(obj) = SDReadPtr(file);
car(obj) = (object *)SDReadInt(file);
cdr(obj) = (object *)SDReadInt(file);
}
file.close();
gc(NULL, NULL);
return imagesize;
#elif defined(ARDUINO_METRO_M4) || defined(ARDUINO_ITSYBITSY_M4) || defined(ARDUINO_FEATHER_M4)
if (!FlashSetup()) error(PSTR("No DataFlash found."));
FlashBeginRead();
FlashReadInt(); // Skip eval address
int imagesize = FlashReadInt();
if (imagesize == 0 || imagesize == 0xFFFF) error(PSTR("No saved image"));
GlobalEnv = (object *)FlashReadInt();
GCStack = (object *)FlashReadInt();
#if SYMBOLTABLESIZE > BUFFERSIZE
SymbolTop = (char *)FlashReadInt();
for (int i=0; i<SYMBOLTABLESIZE; i++) SymbolTable[i] = FlashReadByte();
#endif
for (int i=0; i<imagesize; i++) {
object *obj = &Workspace[i];
car(obj) = (object *)FlashReadInt();
cdr(obj) = (object *)FlashReadInt();
}
gc(NULL, NULL);
FlashEndRead();
return imagesize;
#else
(void) filename;
error(PSTR("load-image not available"));
@ -463,13 +634,22 @@ void autorunimage () {
SD.begin(SDCARD_SS_PIN);
File file = SD.open("ULISP.IMG");
if (!file) error(PSTR("Error: Problem autorunning from SD card"));
object *autorun = SDReadPtr(file);
object *autorun = (object *)SDReadInt(file);
object *nullenv = NULL;
file.close();
if (autorun != NULL) {
loadimage(NULL);
apply(autorun, NULL, &nullenv);
}
#elif defined(ARDUINO_METRO_M4)
object *nullenv = NULL;
FlashBeginRead();
object *autorun = (object *)FlashReadInt();
FlashEndRead();
if (autorun != NULL && (unsigned int)autorun != 0xFFFF) {
loadimage(nil);
apply(autorun, NULL, &nullenv);
}
#else
error(PSTR("autorun not available"));
#endif
@ -904,7 +1084,7 @@ void I2Cstop(uint8_t read) {
// Streams
inline int spiread () { return SPI.transfer(0); }
#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKRZERO)
#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKRZERO) || defined(ARDUINO_METRO_M4) || defined(ARDUINO_ITSYBITSY_M4) || defined(ARDUINO_FEATHER_M4)
inline int serial1read () { while (!Serial1.available()) testescape(); return Serial1.read(); }
#elif defined(ARDUINO_SAM_DUE)
inline int serial1read () { while (!Serial1.available()) testescape(); return Serial1.read(); }
@ -924,7 +1104,7 @@ inline int SDread () {
#endif
void serialbegin (int address, int baud) {
#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKRZERO)
#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKRZERO) || defined(ARDUINO_METRO_M4) || defined(ARDUINO_ITSYBITSY_M4) || defined(ARDUINO_FEATHER_M4)
if (address == 1) Serial1.begin((long)baud*100);
else error(PSTR("'with-serial' port not supported"));
#elif defined(ARDUINO_SAM_DUE)
@ -936,7 +1116,7 @@ void serialbegin (int address, int baud) {
}
void serialend (int address) {
#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKRZERO)
#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKRZERO) || defined(ARDUINO_METRO_M4) || defined(ARDUINO_ITSYBITSY_M4) || defined(ARDUINO_FEATHER_M4)
if (address == 1) Serial1.end();
#elif defined(ARDUINO_SAM_DUE)
if (address == 1) Serial1.end();
@ -980,7 +1160,7 @@ pfun_t pstreamfun (object *args) {
int streamtype = SERIALSTREAM;
int address = 0;
pfun_t pfun = pserial;
if (args != NULL) {
if (args != NULL && first(args) != NULL) {
int stream = istream(first(args));
streamtype = stream>>8; address = stream & 0xFF;
}
@ -1008,6 +1188,12 @@ void checkanalogread (int pin) {
if (!(pin>=14 && pin<=19)) error(PSTR("'analogread' invalid pin"));
#elif defined(ARDUINO_SAMD_MKRZERO)
if (!(pin>=15 && pin<=21)) error(PSTR("'analogread' invalid pin"));
#elif defined(ARDUINO_METRO_M4)
if (!(pin>=14 && pin<=21)) error(PSTR("'analogread' invalid pin"));
#elif defined(ARDUINO_ITSYBITSY_M4)
if (!(pin>=14 && pin<=19)) error(PSTR("'analogread' invalid pin"));
#elif defined(ARDUINO_FEATHER_M4)
if (!(pin>=14 && pin<=19)) error(PSTR("'analogread' invalid pin"));
#elif defined(_VARIANT_BBC_MICROBIT_)
if (!((pin>=0 && pin<=4) || pin==10)) error(PSTR("'analogread' invalid pin"));
#endif
@ -1020,8 +1206,14 @@ void checkanalogwrite (int pin) {
if (!((pin>=3 && pin<=6) || (pin>=8 && pin<=13) || pin==14)) error(PSTR("'analogwrite' invalid pin"));
#elif defined(ARDUINO_SAMD_MKRZERO)
if (!((pin>=0 && pin<=8) || pin==10 || pin==18 || pin==19)) error(PSTR("'analogwrite' invalid pin"));
#elif defined(ARDUINO_METRO_M4)
if (!(pin>=0 && pin<=15)) error(PSTR("'analogwrite' invalid pin"));
#elif defined(ARDUINO_ITSYBITSY_M4)
if (!(pin==0 || pin==1 || pin==4 || pin==5 || pin==7 || (pin>=9 && pin<=15) || pin==21 || pin==22)) error(PSTR("'analogwrite' invalid pin"));
#elif defined(ARDUINO_FEATHER_M4)
if (!(pin==0 || pin==1 || (pin>=4 && pin<=6) || (pin>=9 && pin<=13) || pin==14 || pin==15 || pin==17 || pin==21 || pin==22)) error(PSTR("'analogwrite' invalid pin"));
#elif defined(_VARIANT_BBC_MICROBIT_)
error(PSTR("'analogwrite' not supported"));
if (!(pin>=0 && pin<=2)) error(PSTR("'analogwrite' invalid pin"));
#endif
}
@ -2320,7 +2512,9 @@ object *fn_round (object *args, object *env) {
object *fn_char (object *args, object *env) {
(void) env;
char c = nthchar(first(args), integer(second(args)));
object *arg = first(args);
if (!stringp(arg)) error2(arg, PSTR("is not a string"));
char c = nthchar(arg, integer(second(args)));
if (c == 0) error(PSTR("'char' index out of range"));
return character(c);
}
@ -3875,7 +4069,7 @@ void setup () {
initworkspace();
initenv();
initsleep();
pfstring(PSTR("uLisp 2.3 "), pserial); pln(pserial);
pfstring(PSTR("uLisp 2.4 "), pserial); pln(pserial);
}
// Read/Evaluate/Print loop