Move pin defs into auto-generated header file - allows us to optimise a bit better

This commit is contained in:
Gordon Williams 2013-12-19 11:31:15 +00:00
parent 30327a9f99
commit a79cff3fcd
8 changed files with 103 additions and 87 deletions

View File

@ -732,7 +732,7 @@ endif
ifdef ARM
LINKER_FILE = gen/linker.ld
PININFOFILE=$(ROOT)/gen/jshardware_pininfo.c
PININFOFILE=$(ROOT)/gen/jspininfo
DEFINES += -DARM
INCLUDE += -I$(ROOT)/targetlibs/arm
OPTIMIZEFLAGS += -fno-common -fno-exceptions -fdata-sections -ffunction-sections
@ -751,7 +751,7 @@ export CCPREFIX=arm-none-eabi-
endif # ARM
ifdef PININFOFILE
SOURCES += $(PININFOFILE)
SOURCES += $(PININFOFILE).c
endif
ifdef CARAMBOLA
@ -842,9 +842,9 @@ $(WRAPPERFILE): scripts/build_jswrapper.py $(WRAPPERSOURCES)
$(Q)python scripts/build_jswrapper.py $(WRAPPERSOURCES) $(DEFINES)
ifdef PININFOFILE
$(PININFOFILE): scripts/build_pininfo.py
$(PININFOFILE).c $(PININFOFILE).h: scripts/build_pininfo.py
@echo Generating pin info
$(Q)python scripts/build_pininfo.py $(BOARD) $(PININFOFILE)
$(Q)python scripts/build_pininfo.py $(BOARD) $(PININFOFILE).c $(PININFOFILE).h
endif
$(LINKER_FILE): scripts/build_linker.py

View File

@ -32,12 +32,14 @@ import pinutils;
# Now scan AF file
print "Script location "+scriptdir
if len(sys.argv)!=3:
print "ERROR, USAGE: build_pininfo.py BOARD_NAME PININFO_FILENAME"
if len(sys.argv)!=4:
print "ERROR, USAGE: build_pininfo.py BOARD_NAME jspininfo.c jspininfo.h"
exit(1)
boardname = sys.argv[1]
pininfoFilename = sys.argv[2]
print "PININFO_FILENAME"+pininfoFilename
pininfoSourceFilename = sys.argv[2]
pininfoHeaderFilename = sys.argv[3]
print "PININFO_SOURCE_FILENAME"+pininfoSourceFilename
print "PININFO_HEADER_FILENAME"+pininfoHeaderFilename
print "BOARD "+boardname
# import the board def
@ -50,15 +52,31 @@ pins = board.get_pins()
# -----------------------------------------------------------------------------------------
pininfoFile = open(pininfoFilename, 'w')
def writepininfo(s): pininfoFile.write(s+"\n");
pininfoSourceFile = open(pininfoSourceFilename, 'w')
pininfoHeaderFile = open(pininfoHeaderFilename, 'w')
def writesource(s): pininfoSourceFile.write(s+"\n");
def writeheader(s): pininfoHeaderFile.write(s+"\n");
# -----------------------------------------------------------------------------------------
pinInfoFunctionCount = 0
# work out pin functions (and how many we need)
for pin in pins:
functions = [ ]
for afname in pin["functions"]:
af = pin["functions"][afname]
if afname in pinutils.ALLOWED_FUNCTIONS:
functions.append("JSH_AF"+str(af)+"|"+pinutils.ALLOWED_FUNCTIONS[afname]);
pin["jshFunctions"] = functions
if len(functions)>pinInfoFunctionCount: pinInfoFunctionCount = len(functions)
writesource("// auto-generated pin info file")
writesource("// for board "+boardname)
writesource("#include \"jspininfo.h\"")
writesource("")
writesource("const JshPinInfo pinInfo[JSH_PIN_COUNT] = {")
writepininfo("// auto-generated pin info file")
writepininfo("// for board "+boardname)
writepininfo("#include \"jshardware_pininfo.h\"")
writepininfo("")
writepininfo("const int pinInfoCount = "+str(len(pins))+";")
writepininfo("const JshPinInfo pinInfo[] = {")
for pin in pins:
analog = "JSH_ANALOG_NONE";
for function in pin["functions"]:
@ -67,20 +85,11 @@ for pin in pins:
adc = function[3:inpos]
channel = function[inpos+3:]
analog = "JSH_ANALOG"+adc+"|JSH_ANALOG_CH"+channel;
function = pin["jshFunctions"]
while len(functions)<pinInfoFunctionCount: functions.append("0")
functions = [ ]
for afname in pin["functions"]:
af = pin["functions"][afname]
if afname in pinutils.ALLOWED_FUNCTIONS:
functions.append("JSH_AF"+str(af)+"|"+pinutils.ALLOWED_FUNCTIONS[afname]);
if len(functions)>pinutils.MAX_ALLOWED_FUNCTIONS:
print "ERROR: Too many functions for pin "+pin["name"]+" ("+str(len(functions))+" functions)";
exit(1)
while len(functions)<pinutils.MAX_ALLOWED_FUNCTIONS: functions.append("0")
writepininfo("/* "+pin["name"].ljust(4)+" */ { JSH_PORT"+pin["port"]+", JSH_PIN"+pin["num"]+", "+analog+", "+', '.join(functions)+" },")
writepininfo("};")
writesource("/* "+pin["name"].ljust(4)+" */ { JSH_PORT"+pin["port"]+", JSH_PIN"+pin["num"]+", "+analog+", "+', '.join(functions)+" },")
writesource("};")
portinfo = {}
@ -99,9 +108,29 @@ if boardname=="OLIMEXINO_STM32":
elif port=="D": portinfo[port] = { 'count' : 39, 'offset' : 0 }
else: portinfo[port] = { 'count' : 0, 'offset' : -1 }
for port in pinutils.ALLOWED_PORTS:
writepininfo("const int JSH_PORT"+port+"_COUNT = "+str(portinfo[port]['count'])+";")
for port in pinutils.ALLOWED_PORTS:
writepininfo("const int JSH_PORT"+port+"_OFFSET = "+str(portinfo[port]['offset'])+";")
writesource("")
writeheader("// auto-generated pin info file")
writeheader("// for board "+boardname)
writeheader("")
writeheader("#include \"jspin.h\"")
writeheader("")
writeheader("#define JSH_PIN_COUNT "+str(len(pins)));
writeheader("")
for port in pinutils.ALLOWED_PORTS:
writeheader("#define JSH_PORT"+port+"_COUNT "+str(portinfo[port]['count']))
for port in pinutils.ALLOWED_PORTS:
writeheader("#define JSH_PORT"+port+"_OFFSET "+str(portinfo[port]['offset']))
writeheader("")
writeheader("#define JSH_PININFO_FUNCTIONS "+str(pinInfoFunctionCount))
writeheader("")
writeheader("typedef struct JshPinInfo {")
writeheader(" JsvPinInfoPort port;")
writeheader(" JsvPinInfoPin pin;")
writeheader(" JsvPinInfoAnalog analog; // TODO: maybe we don't need to store analogs separately")
writeheader(" JshPinFunction functions[JSH_PININFO_FUNCTIONS];")
writeheader("} PACKED_FLAGS JshPinInfo;")
writeheader("")
writeheader("extern const JshPinInfo pinInfo[JSH_PIN_COUNT];");

View File

@ -19,7 +19,6 @@ import json;
import sys;
import os;
MAX_ALLOWED_FUNCTIONS = 6
ALLOWED_PORTS = "ABCDEFGH";
ALLOWED_FUNCTIONS = {}
CLASSES = {}

View File

@ -20,8 +20,9 @@
#include "jsutils.h"
#include "jsvar.h"
#include "jsdevices.h"
#include "jspin.h"
#ifndef LINUX
#include "jshardware_pininfo.h"
#include "jspininfo.h"
#else
#include <inttypes.h>
#endif

View File

@ -1,25 +1,22 @@
#ifndef JSHARDWARE_PININFO
#define JSHARDWARE_PININFO
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Utilities and definitions for handling Pins
* ----------------------------------------------------------------------------
*/
#ifndef JSPIN_H
#define JSPIN_H
#include "jsutils.h"
extern const int JSH_PORTA_COUNT;
extern const int JSH_PORTB_COUNT;
extern const int JSH_PORTC_COUNT;
extern const int JSH_PORTD_COUNT;
extern const int JSH_PORTE_COUNT;
extern const int JSH_PORTF_COUNT;
extern const int JSH_PORTG_COUNT;
extern const int JSH_PORTH_COUNT;
extern const int JSH_PORTA_OFFSET;
extern const int JSH_PORTB_OFFSET;
extern const int JSH_PORTC_OFFSET;
extern const int JSH_PORTD_OFFSET;
extern const int JSH_PORTE_OFFSET;
extern const int JSH_PORTF_OFFSET;
extern const int JSH_PORTG_OFFSET;
extern const int JSH_PORTH_OFFSET;
typedef enum {
JSH_PORT_NONE,
JSH_PORTA=1,
@ -141,6 +138,7 @@ typedef enum {
JSH_USARTMAX = JSH_USART6,
// ---------------------------- JSH_MASK_INFO
JSH_TIMER_CH1 = 0x0000,
JSH_TIMER_CH2 = 0x1000,
JSH_TIMER_CH3 = 0x2000,
@ -184,16 +182,4 @@ typedef enum {
(((F)&JSH_MASK_TYPE)<=JSH_SPIMAX))
#define JSH_PININFO_FUNCTIONS 6
typedef struct JshPinInfo {
JsvPinInfoPort port;
JsvPinInfoPin pin;
JsvPinInfoAnalog analog; // TODO: maybe we don't need to store analogs separately
JshPinFunction functions[JSH_PININFO_FUNCTIONS];
} PACKED_FLAGS JshPinInfo;
extern const int pinInfoCount;
extern const JshPinInfo pinInfo[];
#endif //JSHARDWARE_PININFO
#endif //JSPIN_H

View File

@ -277,6 +277,12 @@ typedef enum LEX_TYPES {
LEX_R_LIST_END /* always the last entry */
} LEX_TYPES;
// To handle variable size bit fields
#define BITFIELD_DECL(BITFIELD, N) unsigned int BITFIELD[(N+31)/32]
#define BITFIELD_GET(BITFIELD, N) ((BITFIELD[(N)>>5] >> ((N)&31))&1)
#define BITFIELD_SET(BITFIELD, N, VALUE) (BITFIELD[(N)>>5] = (BITFIELD[(N)>>5]& (unsigned int)~(1 << ((N)&31))) | (unsigned int)((VALUE)?(1 << ((N)&31)):0) )
static inline bool isWhitespace(char ch) {
return (ch==' ') || (ch=='\t') || (ch=='\n') || (ch=='\r');
}

View File

@ -24,7 +24,6 @@
#endif
#include "jshardware.h"
#include "jshardware_pininfo.h"
#include "jsutils.h"
#include "jsparse.h"
#include "jsinteractive.h"
@ -53,7 +52,7 @@
Pin watchedPins[16];
// NOTE: Only works up to 64 IO pins
unsigned long long jshPinStateIsManual = 0;
BITFIELD_DECL(jshPinStateIsManual, JSH_PIN_COUNT);
#ifdef STM32F4
#define WAIT_UNTIL_N_CYCLES 10000000
@ -525,7 +524,7 @@ static void NO_INLINE jshPrintCapablePins(Pin existingPin, const char *functionN
Pin pin;
int i,n=0;
for (pin=0;pin<pinInfoCount;pin++) {
for (pin=0;pin<JSH_PIN_COUNT;pin++) {
bool has = false;
#ifdef STM32F1
int af = 0;
@ -601,14 +600,11 @@ void jshDelayMicroseconds(int microsec) {
}
bool jshGetPinStateIsManual(Pin pin) {
return (jshPinStateIsManual>>pin)&1;
return BITFIELD_GET(jshPinStateIsManual, pin);
}
void jshSetPinStateIsManual(Pin pin, bool manual) {
if (manual)
jshPinStateIsManual = jshPinStateIsManual | (1ULL<<pin);
else
jshPinStateIsManual = jshPinStateIsManual & ~(1ULL<<pin);
void jshSetPinStateIsManual(Pin pin, bool manual) {
BITFIELD_SET(jshPinStateIsManual, pin, manual);
}
inline void jshPinSetState(Pin pin, JshPinState state) {
@ -739,7 +735,7 @@ inline bool jshPinGetValue(Pin pin) {
}
bool jshIsPinValid(Pin pin) {
return pin>=0 && pin < pinInfoCount && pinInfo[pin].port!=JSH_PORT_NONE;
return pin>=0 && pin < JSH_PIN_COUNT && pinInfo[pin].port!=JSH_PORT_NONE;
}
@ -1202,7 +1198,7 @@ bool jshPinInput(Pin pin) {
JsVarFloat jshPinAnalog(Pin pin) {
JsVarFloat value = 0;
if (pin<0 || pin >= pinInfoCount || pinInfo[pin].analog==JSH_ANALOG_NONE) {
if (pin<0 || pin >= JSH_PIN_COUNT || pinInfo[pin].analog==JSH_ANALOG_NONE) {
jshPrintCapablePins(pin, "Analog Input", 0,0,0,0, true);
return 0;
}
@ -1354,7 +1350,7 @@ void jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq) { // if freq
if (value<0) value=0;
if (value>1) value=1;
JshPinFunction func = 0;
if (pin>=0 && pin < pinInfoCount) {
if (pin>=0 && pin < JSH_PIN_COUNT) {
int i;
for (i=0;i<JSH_PININFO_FUNCTIONS;i++) {
if (freq<=0 && JSH_PINFUNCTION_IS_DAC(pinInfo[pin].functions[i])) {
@ -1467,7 +1463,7 @@ void jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq) { // if freq
}
void jshPinWatch(Pin pin, bool shouldWatch) {
if (pin>=0 && pin < pinInfoCount && pinInfo[pin].port!=JSH_PORT_NONE) {
if (jshIsPinValid(pin)) {
// TODO: check for DUPs, also disable interrupt
/*int idx = pinToPinSource(IOPIN_DATA[pin].pin);
if (pinInterrupt[idx].pin>PININTERRUPTS) jsError("Interrupt already used");
@ -1499,7 +1495,7 @@ void jshPinWatch(Pin pin, bool shouldWatch) {
bool jshGetWatchedPinState(IOEventFlags device) {
int exti = IOEVENTFLAGS_GETTYPE(device) - EV_EXTI0;
Pin pin = watchedPins[exti];
if (pin>=0 && pin < pinInfoCount)
if (jshIsPinValid(pin))
return GPIO_ReadInputDataBit(stmPort(pin), stmPin(pin));
return false;
}
@ -1510,7 +1506,7 @@ bool jshIsEventForPin(IOEvent *event, Pin pin) {
/** Try and find a specific type of function for the given pin. Can be given an invalid pin and will return 0. */
JshPinFunction NO_INLINE getPinFunctionForPin(Pin pin, JshPinFunction functionType) {
if (pin<0 || pin>=pinInfoCount) return 0;
if (!jshIsPinValid(pin)) return 0;
int i;
for (i=0;i<JSH_PININFO_FUNCTIONS;i++) {
if ((pinInfo[pin].functions[i]&JSH_MASK_TYPE) == functionType)
@ -1529,14 +1525,14 @@ Pin NO_INLINE findPinForFunction(JshPinFunction functionType, JshPinFunction fun
Pin i;
int j;
// first, try and find the pin with an AF of 0 - this is usually the 'default'
for (i=0;i<pinInfoCount;i++)
for (i=0;i<JSH_PIN_COUNT;i++)
for (j=0;j<JSH_PININFO_FUNCTIONS;j++)
if ((pinInfo[i].functions[j]&JSH_MASK_AF) == JSH_AF0 &&
(pinInfo[i].functions[j]&JSH_MASK_TYPE) == functionType &&
(pinInfo[i].functions[j]&JSH_MASK_INFO) == functionInfo)
return i;
// otherwise just try and find anything
for (i=0;i<pinInfoCount;i++)
for (i=0;i<JSH_PIN_COUNT;i++)
for (j=0;j<JSH_PININFO_FUNCTIONS;j++)
if ((pinInfo[i].functions[j]&JSH_MASK_TYPE) == functionType &&
(pinInfo[i].functions[j]&JSH_MASK_INFO) == functionInfo)
@ -2331,7 +2327,7 @@ void jshPinPulse(Pin pin, bool pulsePolarity, JsVarFloat pulseTime) {
// ---- SOFTWARE PULSE
/* JsSysTime ticks = jshGetTimeFromMilliseconds(time);
//jsPrintInt(ticks);jsPrint("\n");
if (pin>=0 && pin < pinInfoCount && pinInfo[pin].port!=JSH_PORT_NONE) {
if (jshIsPinValid(pin) {
jshPinSetState(pin, JSHPINSTATE_GPIO_OUT);
jshPinSetValue(pin, value);
JsSysTime starttime = jshGetSystemTime();
@ -2345,7 +2341,7 @@ void jshPinPulse(Pin pin, bool pulsePolarity, JsVarFloat pulseTime) {
jshPinSetValue(pin, !value);
} else jsError("Invalid pin!"); */
// ---- USE TIMER FOR PULSE
if (!(pin>=0 && pin < pinInfoCount && pinInfo[pin].port!=JSH_PORT_NONE)) {
if (!jshIsPinValid(pin)) {
jsError("Invalid pin!");
return;
}

View File

@ -28,7 +28,6 @@
#endif
#include "jsinteractive.h"
#include "jshardware.h"
#include "jshardware_pininfo.h"
extern void _VECTOR_TABLE;