Merge remote-tracking branch 'origin/master'
authorKeith Packard <keithp@keithp.com>
Sat, 17 Aug 2013 14:03:26 +0000 (16:03 +0200)
committerKeith Packard <keithp@keithp.com>
Sat, 17 Aug 2013 14:03:26 +0000 (16:03 +0200)
43 files changed:
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
altoslib/AltosConvert.java
altoslib/AltosHeight.java
altoslib/AltosLib.java
altoslib/AltosState.java
altosui/AltosConfigUI.java
altosui/AltosGraph.java
altosui/AltosGraphDataPoint.java
altosuilib/AltosUSBDevice.java
micropeak/MicroPeak.java
src/cc1111/ao_radio.c
src/core/ao_flight.c
src/core/ao_log.c
src/core/ao_log_mega.c
src/drivers/ao_m25.c
src/drivers/ao_pad.c
src/drivers/ao_pca9922.c
src/easymini-v0.1/Makefile
src/easymini-v0.1/ao_pins.h
src/easymini-v0.1/flash-loader/Makefile [new file with mode: 0644]
src/easymini-v0.1/flash-loader/ao_pins.h [new file with mode: 0644]
src/lpc/altos-loader.ld [new file with mode: 0644]
src/lpc/altos-standalone.ld [new file with mode: 0644]
src/lpc/altos.ld
src/lpc/ao_adc_lpc.c
src/lpc/ao_arch.h
src/lpc/ao_arch_funcs.h
src/lpc/ao_boot.h [new file with mode: 0644]
src/lpc/ao_boot_chain.c [new file with mode: 0644]
src/lpc/ao_boot_pin.c [new file with mode: 0644]
src/lpc/ao_flash.h [new file with mode: 0644]
src/lpc/ao_flash_loader_lpc.c [new file with mode: 0644]
src/lpc/ao_flash_lpc_pins.h [new file with mode: 0644]
src/lpc/ao_interrupt.c
src/lpc/ao_spi_lpc.c
src/lpc/ao_timer_lpc.c
src/lpc/ao_usb_lpc.c
src/lpc/lpc.h
src/product/ao_flash_pins.h
src/product/ao_flash_task.c
src/telefire-v0.1/ao_pins.h
src/telefire-v0.2/ao_pins.h
src/test/Makefile

index 0236b537a2271d41028e9ad7d6ab48238a49853a..940ad792df17ff35e6532123d2450ad41481782b 100644 (file)
@@ -36,11 +36,13 @@ import android.os.Handler;
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
+import android.os.Looper;
 import android.util.Log;
 import android.widget.Toast;
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationListener;
+import android.location.Criteria;
 
 import org.altusmetrum.altoslib_1.*;
 
@@ -280,8 +282,8 @@ public class TelemetryService extends Service implements LocationListener {
                // Listen for GPS and Network position updates
                LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
                
-               locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
-               locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
+               locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
+//             locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
        }
 
        @Override
index a42b36c46fc5debdb669ea17f7dd5f88ef379e6f..8cd478e2bd5ff6820bc0e5432deb1d8ad70a4082 100644 (file)
@@ -242,6 +242,10 @@ public class AltosConvert {
                return meters * (100 / (2.54 * 12));
        }
 
+       public static double feet_to_meters(double feet) {
+               return feet * 12 * 2.54 / 100.0;
+       }
+
        public static double meters_to_miles(double meters) {
                return meters_to_feet(meters) / 5280;
        }
index ed590812c5245b7076955b7e583d0337ffc47d4a..96f5722bde80bcca8b3a33d32b3d32b345d2acd4 100644 (file)
@@ -25,6 +25,13 @@ public class AltosHeight extends AltosUnits {
                return v;
        }
 
+       public double parse(String s) throws NumberFormatException {
+               double  v = Double.parseDouble(s);
+               if (AltosConvert.imperial_units)
+                       v = AltosConvert.feet_to_meters(v);
+               return v;
+       }
+
        public String show_units() {
                if (AltosConvert.imperial_units)
                        return "ft";
index a629260bb50d2e0fd844bf8361f31c2cfe43cd1a..d60ef492ccffeb38d89f70d0b02b89e8306e4426 100644 (file)
@@ -92,8 +92,10 @@ public class AltosLib {
        public final static int product_telemega = 0x0023;
        public final static int product_megadongle = 0x0024;
        public final static int product_telegps = 0x0025;
+       public final static int product_easymini = 0x0026;
+       public final static int product_telemini = 0x0027;
        public final static int product_altusmetrum_min = 0x000a;
-       public final static int product_altusmetrum_max = 0x0025;
+       public final static int product_altusmetrum_max = 0x002c;
 
        public final static int product_any = 0x10000;
        public final static int product_basestation = 0x10000 + 1;
index 825306be998559373141bba449553019605fa18c..e0d9bb1fc394dc1cb42b495bc03e755d135968bb 100644 (file)
@@ -40,6 +40,7 @@ public class AltosState {
        public double   ground_altitude;
        public double   altitude;
        public double   height;
+       public double   pressure;
        public double   acceleration;
        public double   battery;
        public double   temperature;
@@ -125,6 +126,7 @@ public class AltosState {
                drogue_sense = data.drogue_voltage();
                main_sense = data.main_voltage();
                battery = data.battery_voltage();
+               pressure = data.pressure();
                tick = data.tick;
                state = data.state;
 
index 11f405938ba385118eed7bbf57c6665f20d93b55..9723e6600141549237244cac29c878787df9ae1a 100644 (file)
@@ -26,7 +26,7 @@ import org.altusmetrum.altosuilib_1.*;
 
 public class AltosConfigUI
        extends AltosUIDialog
-       implements ActionListener, ItemListener, DocumentListener, AltosConfigValues
+       implements ActionListener, ItemListener, DocumentListener, AltosConfigValues, AltosUnitsListener
 {
 
        Container       pane;
@@ -75,11 +75,16 @@ public class AltosConfigUI
 
        ActionListener  listener;
 
-       static String[] main_deploy_values = {
+       static String[] main_deploy_values_m = {
                "100", "150", "200", "250", "300", "350",
                "400", "450", "500"
        };
 
+       static String[] main_deploy_values_ft = {
+               "250", "500", "750", "1000", "1250", "1500",
+               "1750", "2000"
+       };
+
        static String[] apogee_delay_values = {
                "0", "1", "2", "3", "4", "5"
        };
@@ -280,7 +285,7 @@ public class AltosConfigUI
                c.anchor = GridBagConstraints.LINE_START;
                c.insets = il;
                c.ipady = 5;
-               main_deploy_label = new JLabel("Main Deploy Altitude(m):");
+               main_deploy_label = new JLabel(get_main_deploy_label());
                pane.add(main_deploy_label, c);
 
                c = new GridBagConstraints();
@@ -291,7 +296,7 @@ public class AltosConfigUI
                c.anchor = GridBagConstraints.LINE_START;
                c.insets = ir;
                c.ipady = 5;
-               main_deploy_value = new JComboBox(main_deploy_values);
+               main_deploy_value = new JComboBox(main_deploy_values());
                main_deploy_value.setEditable(true);
                main_deploy_value.addItemListener(this);
                pane.add(main_deploy_value, c);
@@ -616,6 +621,7 @@ public class AltosConfigUI
                close.setActionCommand("Close");
 
                addWindowListener(new ConfigListener(this));
+               AltosPreferences.register_units_listener(this);
        }
 
        /* Once the initial values are set, the config code will show the dialog */
@@ -654,6 +660,10 @@ public class AltosConfigUI
 
        AltosConfigPyroUI       pyro_ui;
 
+       public void dispose() {
+               AltosPreferences.unregister_units_listener(this);
+       }
+
        /* Listen for events from our buttons */
        public void actionPerformed(ActionEvent e) {
                String  cmd = e.getActionCommand();
@@ -718,12 +728,38 @@ public class AltosConfigUI
        }
 
        public void set_main_deploy(int new_main_deploy) {
-               main_deploy_value.setSelectedItem(Integer.toString(new_main_deploy));
+               main_deploy_value.setSelectedItem(AltosConvert.height.say(new_main_deploy));
                main_deploy_value.setEnabled(new_main_deploy >= 0);
        }
 
        public int main_deploy() {
-               return Integer.parseInt(main_deploy_value.getSelectedItem().toString());
+               return (int) (AltosConvert.height.parse(main_deploy_value.getSelectedItem().toString()) + 0.5);
+       }
+
+       String get_main_deploy_label() {
+               return String.format("Main Deploy Altitude(%s):", AltosConvert.height.show_units());
+       }
+       
+       String[] main_deploy_values() {
+               if (AltosConvert.imperial_units)
+                       return main_deploy_values_ft;
+               else
+                       return main_deploy_values_m;
+       }
+                       
+       void set_main_deploy_values() {
+               String[]        v = main_deploy_values();
+               while (main_deploy_value.getItemCount() > 0)
+                       main_deploy_value.removeItemAt(0);
+               for (int i = 0; i < v.length; i++)
+                       main_deploy_value.addItem(v[i]);
+               main_deploy_value.setMaximumRowCount(v.length);
+       }
+       
+       public void units_changed(boolean imperial_units) {
+               main_deploy_label.setText(get_main_deploy_label());
+               set_main_deploy_values();
+               listener.actionPerformed(new ActionEvent(this, 0, "Reset"));
        }
 
        public void set_apogee_delay(int new_apogee_delay) {
index defe69a0082cdca7a061331cd5086bf3404e772a..40604ce3574060a3a20d09f62244ac6a32f6d3c0 100644 (file)
@@ -73,18 +73,18 @@ class AltosNsat extends AltosUnits {
        }
 }
 
-class AltosDbm extends AltosUnits {
+class AltosPressure extends AltosUnits {
 
-       public double value(double v) {
-               return v;
+       public double value(double p) {
+               return p;
        }
 
        public String show_units() {
-               return "dBm";
+               return "Pa";
        }
 
        public String say_units() {
-               return "d b m";
+               return "pascals";
        }
 
        public int show_fraction(int width) {
@@ -96,6 +96,7 @@ public class AltosGraph extends AltosUIGraph {
 
        static final private Color height_color = new Color(194,31,31);
        static final private Color gps_height_color = new Color(150,31,31);
+       static final private Color pressure_color = new Color (225,31,31);
        static final private Color range_color = new Color(100, 31, 31);
        static final private Color distance_color = new Color(100, 31, 194);
        static final private Color speed_color = new Color(31,194,31);
@@ -112,16 +113,18 @@ public class AltosGraph extends AltosUIGraph {
        static final private Color state_color = new Color(0,0,0);
 
        static AltosVoltage voltage_units = new AltosVoltage();
+       static AltosPressure pressure_units = new AltosPressure();
        static AltosNsat nsat_units = new AltosNsat();
        static AltosDbm dbm_units = new AltosDbm();
 
        AltosUIAxis     height_axis, speed_axis, accel_axis, voltage_axis, temperature_axis, nsat_axis, dbm_axis;
-       AltosUIAxis     distance_axis;
+       AltosUIAxis     distance_axis, pressure_axis;
 
        public AltosGraph(AltosUIEnable enable, AltosFlightStats stats, AltosGraphDataSet dataSet) {
                super(enable);
 
                height_axis = newAxis("Height", AltosConvert.height, height_color);
+               pressure_axis = newAxis("Pressure", pressure_units, pressure_color, 0);
                speed_axis = newAxis("Speed", AltosConvert.speed, speed_color);
                accel_axis = newAxis("Acceleration", AltosConvert.accel, accel_color);
                voltage_axis = newAxis("Voltage", voltage_units, voltage_color);
@@ -138,6 +141,12 @@ public class AltosGraph extends AltosUIGraph {
                          height_color,
                          true,
                          height_axis);
+               addSeries("Pressure",
+                         AltosGraphDataPoint.data_pressure,
+                         pressure_units,
+                         pressure_color,
+                         false,
+                         pressure_axis);
                addSeries("Speed",
                          AltosGraphDataPoint.data_speed,
                          AltosConvert.speed,
index 8e6d6923327feb670f339a9bd0f8af3b19cfc4fd..7454f447948e897b2a468af31820f0ee42df8593 100644 (file)
@@ -39,6 +39,7 @@ public class AltosGraphDataPoint implements AltosUIDataPoint {
        public static final int data_temperature = 12;
        public static final int data_range = 13;
        public static final int data_distance = 14;
+       public static final int data_pressure = 15;
 
        public double x() throws AltosUIDataMissing {
                if (state.data.time < -2)
@@ -94,6 +95,9 @@ public class AltosGraphDataPoint implements AltosUIDataPoint {
                        if (state.from_pad != null)
                                y = state.from_pad.distance;
                        break;
+               case data_pressure:
+                       y = state.pressure;
+                       break;
                }
                if (y == AltosRecord.MISSING)
                        throw new AltosUIDataMissing(index);
index a06b686911423c1ad4aa1416f37124f8f6dbe665..005a3e4987d377c330c12efb3a8c8728acb7cbee 100644 (file)
@@ -77,7 +77,9 @@ public class AltosUSBDevice  extends altos_device implements AltosDevice {
                if (want_product == AltosUILib.product_altimeter)
                        return matchProduct(AltosUILib.product_telemetrum) ||
                                matchProduct(AltosUILib.product_telemega) ||
-                               matchProduct(AltosUILib.product_telegps);
+                               matchProduct(AltosUILib.product_telegps) ||
+                               matchProduct(AltosUILib.product_easymini) ||
+                               matchProduct(AltosUILib.product_telemini);
 
                int have_product = getProduct();
 
index 792231768808a04011246d2561c29b637bffb8ef..cb1c68cbba2eb7afbc55fe3580a0ff5bce1f5d2f 100644 (file)
@@ -231,6 +231,10 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
                fileMenu.add(exitAction);
                exitAction.addActionListener(this);
 
+               JButton downloadButton = new JButton ("Download");
+               downloadButton.addActionListener(this);
+               menuBar.add(downloadButton);
+
                setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
                addWindowListener(new WindowAdapter() {
                        @Override
index 88b8f686e21c09f1c8193076e0f12d5bf4cc2c0c..190647ce0dbe432f6a0b4ee5f8428b686110cf69 100644 (file)
@@ -374,7 +374,7 @@ ao_radio_recv(__xdata void *packet, uint8_t size, uint8_t timeout) __reentrant
        }
 #if NEED_RADIO_RSSI
        else
-               ao_radio_rssi = AO_RSSI_FROM_RADIO(((uint8_t *)packet)[size - 1]);
+               ao_radio_rssi = AO_RSSI_FROM_RADIO(((uint8_t *)packet)[size - 2]);
 #endif
        ao_radio_put();
        return ao_radio_dma_done;
index 782e22744c434dc28e9356d60708ef728f7e9380..1322195beb2ca4d0e1cb5ddab0c99580e7f2abe5 100644 (file)
@@ -117,7 +117,7 @@ ao_flight(void)
                        {
                                /* Set pad mode - we can fly! */
                                ao_flight_state = ao_flight_pad;
-#if HAS_USB && HAS_RADIO && !HAS_FLIGHT_DEBUG && !HAS_SAMPLE_PROFILE
+#if HAS_USB && !HAS_FLIGHT_DEBUG && !HAS_SAMPLE_PROFILE
                                /* Disable the USB controller in flight mode
                                 * to save power
                                 */
index 7884ec3cde155a88102e56db5905f2e57535ae95..8bcb770763c0efe70ad1917c4d8caabc14ab257c 100644 (file)
@@ -278,6 +278,11 @@ ao_log_init(void)
 
        ao_cmd_register(&ao_log_cmds[0]);
 
+#ifndef HAS_ADC
+#error Define HAS_ADC for ao_log.c
+#endif
+#if HAS_ADC
        /* Create a task to log events to eeprom */
        ao_add_task(&ao_log_task, ao_log, "log");
+#endif
 }
index ee12b907b7b7b295ec2ce9e6c4b280e1f9c74d7f..768947d541728159f7e86d16c30d2122ad4a4914 100644 (file)
@@ -65,6 +65,7 @@ ao_log_dump_check_data(void)
        return 1;
 }
 
+#if HAS_ADC
 static __data uint8_t  ao_log_data_pos;
 
 /* a hack to make sure that ao_log_megas fill the eeprom block in even units */
@@ -182,6 +183,7 @@ ao_log(void)
                        ao_sleep(&ao_log_running);
        }
 }
+#endif
 
 uint16_t
 ao_log_flight(uint8_t slot)
index 9b768012a06b03b633fccb45f9b3b3fa9742422e..e6c7bb4db0c0f8d5e23a66261d8de690546e24bc 100644 (file)
@@ -86,7 +86,7 @@ static ao_port_t ao_m25_pin[M25_MAX_CHIPS];   /* chip select pin for each chip */
 static uint8_t ao_m25_numchips;                        /* number of chips detected */
 #endif
 static uint8_t ao_m25_total;                   /* total sectors available */
-static uint8_t ao_m25_wip;                     /* write in progress */
+static ao_port_t ao_m25_wip;                   /* write in progress */
 
 static __xdata uint8_t ao_m25_mutex;
 
@@ -250,7 +250,6 @@ ao_storage_erase(uint32_t pos) __reentrant
 
        cs = ao_m25_set_address(pos);
 
-       ao_m25_wait_wip(cs);
        ao_m25_write_enable(cs);
 
        ao_m25_instruction[0] = M25_SE;
index e205f99b5e26a1b360cac76a6f821dd305e565a9..62ae68e98d976dcdabee72103ce32300ad355e21 100644 (file)
@@ -27,6 +27,7 @@ static __pdata uint8_t        ao_pad_armed;
 static __pdata uint16_t        ao_pad_arm_time;
 static __pdata uint8_t ao_pad_box;
 static __xdata uint8_t ao_pad_disabled;
+static __pdata uint16_t        ao_pad_packet_time;
 
 #define DEBUG  1
 
@@ -135,6 +136,12 @@ ao_pad_monitor(void)
                        query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN;
                        arm_beep_time = 0;
                }
+               if ((ao_time() - ao_pad_packet_time) > AO_SEC_TO_TICKS(2))
+                       cur |= AO_LED_RED;
+               else if (ao_radio_cmac_rssi < -90)
+                       cur |= AO_LED_AMBER;
+               else
+                       cur |= AO_LED_GREEN;
 
                for (c = 0; c < AO_PAD_NUM; c++) {
                        int16_t         sense = packet->adc.sense[c];
@@ -171,9 +178,10 @@ ao_pad_monitor(void)
                        query.igniter_status[c] = status;
                }
                if (cur != prev) {
-                       PRINTD("change leds from %02x to %02x mask %02x\n",
-                              prev, cur, AO_LED_CONTINUITY_MASK|AO_LED_ARMED);
-                       ao_led_set_mask(cur, AO_LED_CONTINUITY_MASK | AO_LED_ARMED);
+                       PRINTD("change leds from %02x to %02x\n",
+                              prev, cur);
+                       FLUSHD();
+                       ao_led_set(cur);
                        prev = cur;
                }
 
@@ -238,15 +246,15 @@ ao_pad(void)
 
        ao_pad_box = 0;
        ao_led_set(0);
-       ao_led_on(AO_LED_POWER);
        for (;;) {
                FLUSHD();
                while (ao_pad_disabled)
                        ao_sleep(&ao_pad_disabled);
                ret = ao_radio_cmac_recv(&command, sizeof (command), 0);
-               PRINTD ("cmac_recv %d\n", ret);
+               PRINTD ("cmac_recv %d %d\n", ret, ao_radio_cmac_rssi);
                if (ret != AO_RADIO_CMAC_OK)
                        continue;
+               ao_pad_packet_time = ao_time();
                
                ao_pad_box = ao_pad_read_box();
 
index 6d8d18d8f8eb7df1880eb9d3ca29887786180515..fe070b884909260b028ee53930b2698d59186c71 100644 (file)
@@ -30,9 +30,12 @@ ao_led_apply(void)
        /* Don't try the SPI bus during initialization */
        if (!ao_cur_task)
                return;
-       ao_spi_get_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS, AO_SPI_SPEED_FAST);
+       ao_mutex_get(&ao_spi_mutex);
+       ao_spi_set_speed(AO_SPI_SPEED_FAST);
+       AO_PCA9922_CS = 1;
        ao_spi_send(&ao_led_state, 1, AO_PCA9922_SPI_BUS);
-       ao_spi_put_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS);
+       AO_PCA9922_CS = 0;
+       ao_mutex_put(&ao_spi_mutex);
 }
 
 void
index 612cc47238dfe738c95ffd04de12c6d84e726986..9847656c4f1e7240a6e0999b77374451a64b450a 100644 (file)
@@ -18,6 +18,7 @@ INC = \
 #
 ALTOS_SRC = \
        ao_interrupt.c \
+       ao_boot_chain.c \
        ao_romconfig.c \
        ao_product.c \
        ao_mutex.c \
@@ -39,7 +40,6 @@ ALTOS_SRC = \
        ao_config.c \
        ao_timer_lpc.c \
        ao_exti_lpc.c \
-       ao_serial_lpc.c \
        ao_usb_lpc.c \
        ao_spi_lpc.c \
        ao_adc_lpc.c \
@@ -49,7 +49,7 @@ ALTOS_SRC = \
 
 PRODUCT=EasyMini-v0.1
 PRODUCT_DEF=-DEASYMINI_V_0_1
-IDPRODUCT=0x000a
+IDPRODUCT=0x0026
 
 CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os
 
@@ -63,7 +63,7 @@ all: $(PROG)
 
 LDFLAGS=-L../lpc -Wl,-Taltos.ld
 
-$(PROG): Makefile $(OBJ)
+$(PROG): Makefile $(OBJ) altos.ld
        $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc
 
 ao_product.h: ao-make-product.5c ../Version
index d4fbe7a1e176e4e018e19f9c3b6d1b4f9a58bf12..6f102dbecfb41a4b785310e3004b85489047f0e7 100644 (file)
@@ -18,6 +18,8 @@
 #define HAS_BEEP       1
 #define        HAS_LED         1
 
+#define IS_FLASH_LOADER        0
+
 /* Crystal on the board */
 #define AO_LPC_CLKIN   12000000
 
 
 #define HAS_USB_CONNECT        0
 #define HAS_USB_VBUS   0
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT     0
+#define AO_USB_PULLUP_PIN      20
 
 #define PACKET_HAS_SLAVE       0
 
 /* USART */
 
-#define HAS_SERIAL             1
+#define HAS_SERIAL             0
 #define USE_SERIAL_0_STDIN     1
 #define SERIAL_0_18_19         1
 #define SERIAL_0_14_15         0
diff --git a/src/easymini-v0.1/flash-loader/Makefile b/src/easymini-v0.1/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..ab828b2
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=easymini-v0.1
+include $(TOPDIR)/lpc/Makefile-flash.defs
diff --git a/src/easymini-v0.1/flash-loader/ao_pins.h b/src/easymini-v0.1/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..4330151
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_lpc_pins.h>
+
+#define AO_BOOT_PIN            1
+#define AO_BOOT_APPLICATION_GPIO       0
+#define AO_BOOT_APPLICATION_PIN                19
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT     0
+#define AO_USB_PULLUP_PIN      20
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/lpc/altos-loader.ld b/src/lpc/altos-loader.ld
new file mode 100644 (file)
index 0000000..4f78f55
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+MEMORY {
+       rom : ORIGIN = 0x00000000, LENGTH = 4K
+       ram : ORIGIN = 0x10000000, LENGTH = 4k - 128 - 32
+       usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256
+       stack (!w) : ORIGIN = 0x10000000 + 4K - 128 - 32, LENGTH = 128
+}
+
+INCLUDE registers.ld
+
+EXTERN (lpc_interrupt_vector)
+
+SECTIONS {
+       /*
+        * Rom contents
+        */
+
+       .interrupt : {
+               __text_start__ = .;
+               *(.interrupt)   /* Interrupt vectors */
+
+       } > rom
+
+       .text ORIGIN(rom) + 0x100 : {
+               ao_romconfig.o(.romconfig*)
+               ao_product.o(.romconfig*)
+
+               *(.text*)       /* Executable code */
+               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+               *(.rodata*)     /* Constants */
+               __text_end__ = .;
+       } > rom
+
+       /* Boot data which must live at the start of ram so that
+        * the application and bootloader share the same addresses.
+        * This must be all uninitialized data
+        */
+       .boot ORIGIN(ram) + SIZEOF(.interrupt) (NOLOAD) : {
+               __boot_start__ = .;
+               *(.boot)
+               __boot_end__ = .;
+       } >ram
+
+       /* Data -- relocated to RAM, but written to ROM
+        */
+       .data : {
+               __data_start__ = .;
+               *(.data)        /* initialized data */
+               __data_end__ = .;
+       } >ram AT>rom
+
+
+       .bss : {
+               __bss_start__ = .;
+               *(.bss)
+               *(COMMON)
+               __bss_end__ = .;
+       } >ram
+
+       PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram));
+       PROVIDE(end = .);
+}
+
+ENTRY(start);
diff --git a/src/lpc/altos-standalone.ld b/src/lpc/altos-standalone.ld
new file mode 100644 (file)
index 0000000..032406f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+MEMORY {
+       rom (rx) : ORIGIN = 0x00000000, LENGTH = 32K
+       ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 128 - 32
+       usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256
+       stack (!w) : ORIGIN = 0x10000000 + 4K - 128 - 32, LENGTH = 128
+}
+
+INCLUDE registers.ld
+
+EXTERN (lpc_interrupt_vector)
+
+SECTIONS {
+       /*
+        * Rom contents
+        */
+
+       .text ORIGIN(rom) : {
+               __text_start__ = .;
+               *(.interrupt)   /* Interrupt vectors */
+
+               . = ORIGIN(rom) + 0x100;
+
+               ao_romconfig.o(.romconfig*)
+               ao_product.o(.romconfig*)
+
+               *(.text*)       /* Executable code */
+               *(.rodata*)     /* Constants */
+
+       } > rom
+
+       .ARM.exidx : {
+               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+               __text_end__ = .;
+       } > rom
+
+       /* Boot data which must live at the start of ram so that
+        * the application and bootloader share the same addresses.
+        * This must be all uninitialized data
+        */
+       .boot (NOLOAD) : {
+               __boot_start__ = .;
+               *(.boot)
+               . = ALIGN(4);
+               __boot_end__ = .;
+       } >ram
+
+       /* Data -- relocated to RAM, but written to ROM
+        */
+       .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) {
+               __data_start__ = .;
+               *(.data)        /* initialized data */
+               __data_end__ = .;
+               __bss_start__ = .;
+       } >ram
+
+       .bss : {
+               *(.bss)
+               *(COMMON)
+               __bss_end__ = .;
+       } >ram
+       PROVIDE(end = .);
+
+       PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack));
+}
+
+ENTRY(start);
+
+
index 4d6f35a82a32b83574fffa1730dea574d853d9c4..00d4f18a67e275645f9cd34cbe4fcce669199994 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 MEMORY {
-       rom (rx) : ORIGIN = 0x00000000, LENGTH = 32K
+       rom (rx) : ORIGIN = 0x00001000, LENGTH = 28K
        ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 128
        usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256
        stack (!w) : ORIGIN = 0x10000000 + 4K - 128, LENGTH = 128
@@ -31,11 +31,15 @@ SECTIONS {
         * Rom contents
         */
 
-       .text ORIGIN(rom) : {
-               __text_start__ = .;
+       .interrupt ORIGIN(ram) : AT (ORIGIN(rom)) {
+               __interrupt_start__ = .;
+               __interrupt_rom__ = ORIGIN(rom);
                *(.interrupt)   /* Interrupt vectors */
+               __interrupt_end__ = .;
+       } > ram
 
-               . = ORIGIN(rom) + 0x100;
+       .text ORIGIN(rom) + 0x100 : {
+               __text_start__ = .;
 
                ao_romconfig.o(.romconfig*)
                ao_product.o(.romconfig*)
@@ -50,9 +54,20 @@ SECTIONS {
                __text_end__ = .;
        } > rom
 
+       /* Boot data which must live at the start of ram so that
+        * the application and bootloader share the same addresses.
+        * This must be all uninitialized data
+        */
+       .boot : {
+               __boot_start__ = .;
+               *(.boot)
+               . = ALIGN(4);
+               __boot_end__ = .;
+       } >ram
+
        /* Data -- relocated to RAM, but written to ROM
         */
-       .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) {
+       .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) {
                __data_start__ = .;
                *(.data)        /* initialized data */
                __data_end__ = .;
@@ -60,6 +75,7 @@ SECTIONS {
        } >ram
 
        .bss : {
+               __bss_start__ = .;
                *(.bss)
                *(COMMON)
                __bss_end__ = .;
index 9ecc7c13f1e313d572d98e1bad45d4eb4aefcbd0..874d2d294cb6a08db5a7bd3f9731953f3beb890a 100644 (file)
 # endif
 #endif
 
-static uint8_t                 ao_adc_ready;
+#define AO_ADC_MASK    ((AO_ADC_0 << 0) |      \
+                        (AO_ADC_1 << 1) |      \
+                        (AO_ADC_2 << 2) |      \
+                        (AO_ADC_3 << 3) |      \
+                        (AO_ADC_4 << 4) |      \
+                        (AO_ADC_5 << 5) |      \
+                        (AO_ADC_6 << 6) |      \
+                        (AO_ADC_7 << 7))
+
+#define AO_ADC_CLKDIV  (AO_LPC_SYSCLK / 4500000)
+
+static uint8_t         ao_adc_ready;
+
+#define sample(id)     (*out++ = lpc_adc.dr[id] >> 1)
 
 void  lpc_adc_isr(void)
 {
        uint32_t        stat = lpc_adc.stat;
-       uint16_t        *out = (uint16_t *) &ao_data_ring[ao_data_head].adc;
-       vuint32_t       *in = &lpc_adc.dr[0];
+       uint16_t        *out;
 
+       /* Turn off burst mode */
        lpc_adc.cr = 0;
        lpc_adc.stat = 0;
 
        /* Store converted values in packet */
 
+       out = (uint16_t *) &ao_data_ring[ao_data_head].adc;
 #if AO_ADC_0
-       *out++ = lpc_adc.dr[0] >> 1;
+       sample(0);
 #endif
 #if AO_ADC_1
-       *out++ = lpc_adc.dr[1] >> 1;
+       sample(1);
 #endif
 #if AO_ADC_2
-       *out++ = lpc_adc.dr[2] >> 1;
+       sample(2);
 #endif
 #if AO_ADC_3
-       *out++ = lpc_adc.dr[3] >> 1;
+       sample(3);
 #endif
 #if AO_ADC_4
-       *out++ = lpc_adc.dr[4] >> 1;
+       sample(4);
 #endif
 #if AO_ADC_5
-       *out++ = lpc_adc.dr[5] >> 1;
+       sample(5); 
 #endif
 #if AO_ADC_6
-       *out++ = lpc_adc.dr[6] >> 1;
+       sample(6);
 #endif
 #if AO_ADC_7
-       *out++ = lpc_adc.dr[7] >> 1;
+       sample(7);
 #endif
 
        AO_DATA_PRESENT(AO_DATA_ADC);
@@ -141,16 +155,6 @@ void  lpc_adc_isr(void)
        ao_adc_ready = 1;
 }
 
-#define AO_ADC_MASK    ((AO_ADC_0 << 0) |      \
-                        (AO_ADC_1 << 1) |      \
-                        (AO_ADC_2 << 2) |      \
-                        (AO_ADC_3 << 3) |      \
-                        (AO_ADC_4 << 4) |      \
-                        (AO_ADC_5 << 5) |      \
-                        (AO_ADC_6 << 6) |      \
-                        (AO_ADC_7 << 7))
-
-#define AO_ADC_CLKDIV  (AO_LPC_CLKOUT / 4500000)
 
 /*
  * Start the ADC sequence using the DMA engine
@@ -204,29 +208,35 @@ ao_adc_init(void)
        lpc_nvic_set_enable(LPC_ISR_ADC_POS);
        lpc_nvic_set_priority(LPC_ISR_ADC_POS, AO_LPC_NVIC_CLOCK_PRIORITY);
 #if AO_ADC_0
-       ao_enable_analog(0, 11);
+       ao_enable_analog(0, 11, 0);
 #endif
 #if AO_ADC_1
-       ao_enable_analog(0, 12);
+       ao_enable_analog(0, 12, 1);
 #endif
 #if AO_ADC_2
-       ao_enable_analog(0, 13);
+       ao_enable_analog(0, 13, 2);
 #endif
 #if AO_ADC_3
-       ao_enable_analog(0, 14);
+       ao_enable_analog(0, 14, 3);
 #endif
 #if AO_ADC_4
-       ao_enable_analog(0, 14);
+       ao_enable_analog(0, 15, 4);
 #endif
 #if AO_ADC_5
-       ao_enable_analog(0, 14);
+       ao_enable_analog(0, 16, 5);
 #endif
 #if AO_ADC_6
-       ao_enable_analog(0, 14);
+       ao_enable_analog(0, 22, 6);
 #endif
 #if AO_ADC_7
-       ao_enable_analog(0, 14);
+       ao_enable_analog(0, 23, 7);
 #endif
+
+       lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) |
+                     (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) |
+                     (0 << LPC_ADC_CR_BURST) |
+                     (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS));
+
        ao_cmd_register(&ao_adc_cmds[0]);
 
        ao_adc_ready = 1;
index f605e3d2d677ddc4ed4b5ada58e46ecb88a0d4b9..a8d3cfc4435a0d03c77501e75ac0000684b1f5e0 100644 (file)
@@ -137,4 +137,8 @@ ao_serial_init(void);
 
 #define AO_SPI_SPEED_FAST      AO_SPI_SPEED_12MHz
 
+#define AO_BOOT_APPLICATION_BASE       ((uint32_t *) 0x00001000)
+#define AO_BOOT_LOADER_BASE            ((uint32_t *) 0x00000000)
+#define HAS_BOOT_LOADER                        1
+
 #endif /* _AO_ARCH_H_ */
index 204d1227dd5f525d02579efd85dac30db4a55096..9a3219a2e6275e55a6972dcdf5fff53a390b75c5 100644 (file)
 #define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1<<bit),bus)
 
 #define ao_enable_port(port) (lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO))
+#define ao_disable_port(port) (lpc_scb.sysahbclkctrl &= ~(1 << LPC_SCB_SYSAHBCLKCTRL_GPIO))
 
 #define lpc_all_bit(port,bit)  (((port) << 5) | (bit))
 
 #define ao_gpio_set(port, bit, pin, v) (lpc_gpio.byte[lpc_all_bit(port,bit)] = (v))
 
-#define ao_gpio_get(port, bit, pin)    (lpc_gpio_byte[lpc_all_bit(port,bit)])
+#define ao_gpio_get(port, bit, pin)    (lpc_gpio.byte[lpc_all_bit(port,bit)])
 
 #define ao_enable_output(port,bit,pin,v) do {                  \
                ao_enable_port(port);                           \
                lpc_gpio.dir[port] |= (1 << bit);               \
        } while (0)
 
-#define ao_enable_input(port,bit,mode) do {                            \
+#define ao_gpio_set_mode(port,bit,mode) do {                           \
                vuint32_t *_ioconf = &lpc_ioconf.pio0_0 + ((port)*24+(bit)); \
                vuint32_t _mode;                                        \
-               ao_enable_port(port);                                   \
-               lpc_gpio.dir[port] &= ~(1 << bit);                      \
                if (mode == AO_EXTI_MODE_PULL_UP)                       \
                        _mode = LPC_IOCONF_MODE_PULL_UP << LPC_IOCONF_MODE; \
                else if (mode == AO_EXTI_MODE_PULL_DOWN)                \
                            (1 << LPC_IOCONF_ADMODE));                  \
        } while (0)
 
-#define ao_enable_analog(port,bit) do {                                        \
-               vuint32_t *_ioconf = &lpc_ioconf.pio0_0 + ((port)*24+(bit)); \
+#define ao_enable_input(port,bit,mode) do {                            \
                ao_enable_port(port);                                   \
                lpc_gpio.dir[port] &= ~(1 << bit);                      \
-               *_ioconf = *_ioconf & ~((1 << LPC_IOCONF_ADMODE) |      \
-                                       (LPC_IOCONF_MODE_MASK << LPC_IOCONF_MODE)); \
+               ao_gpio_set_mode(port,bit,mode);                        \
+       } while (0)
+
+#define lpc_token_paster_2(x,y)                x ## y
+#define lpc_token_evaluator_2(x,y)     lpc_token_paster_2(x,y)
+#define lpc_token_paster_3(x,y,z)      x ## y ## z
+#define lpc_token_evaluator_3(x,y,z)   lpc_token_paster_3(x,y,z)
+#define lpc_token_paster_4(w,x,y,z)    w ## x ## y ## z
+#define lpc_token_evaluator_4(w,x,y,z) lpc_token_paster_4(w,x,y,z)
+#define analog_reg(port,bit)           lpc_token_evaluator_4(pio,port,_,bit)
+#define analog_func(id)                        lpc_token_evaluator_2(LPC_IOCONF_FUNC_AD,id)
+
+#define ao_enable_analog(port,bit,id) do {                             \
+               ao_enable_port(port);                                   \
+               lpc_gpio.dir[port] &= ~(1 << bit);                      \
+               lpc_ioconf.analog_reg(port,bit) = ((analog_func(id) << LPC_IOCONF_FUNC) | \
+                                                  (0 << LPC_IOCONF_ADMODE)); \
        } while (0)
        
 #define ARM_PUSH32(stack, val) (*(--(stack)) = (val))
@@ -79,6 +92,7 @@ ao_arch_memory_barrier() {
        asm volatile("" ::: "memory");
 }
 
+#if HAS_TASK
 static inline void
 ao_arch_init_stack(struct ao_task *task, void *start)
 {
@@ -145,6 +159,8 @@ static inline void ao_arch_restore_stack(void) {
 
 #define ao_arch_isr_stack()
 
+#endif /* HAS_TASK */
+
 #define ao_arch_wait_interrupt() do {                  \
                asm(".global ao_idle_loc\n\twfi\nao_idle_loc:");        \
                ao_arch_release_interrupts();                           \
diff --git a/src/lpc/ao_boot.h b/src/lpc/ao_boot.h
new file mode 100644 (file)
index 0000000..e0ed4de
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_BOOT_H_
+#define _AO_BOOT_H_
+
+void
+ao_boot_chain(uint32_t *base);
+
+void
+ao_boot_check_pin(void);
+
+/* Return true to switch to application (if present) */
+int
+ao_boot_check_chain(void);
+
+void
+ao_boot_reboot(uint32_t *base);
+
+static inline void
+ao_boot_loader(void) {
+       ao_boot_reboot(AO_BOOT_LOADER_BASE);
+}
+
+#endif /* _AO_BOOT_H_ */
diff --git a/src/lpc/ao_boot_chain.c b/src/lpc/ao_boot_chain.c
new file mode 100644 (file)
index 0000000..a08d1f2
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_boot.h>
+
+void
+ao_boot_chain(uint32_t *base)
+{
+       uint32_t        sp;
+       uint32_t        pc;
+
+       sp = base[0];
+       pc = base[1];
+       if (0x00000100 <= pc && pc <= 0x00008000 && (pc & 1) == 1) {
+               asm ("mov sp, %0" : : "r" (sp));
+               asm ("mov lr, %0" : : "r" (pc));
+               asm ("bx lr");
+       }
+}
+
+#define AO_BOOT_SIGNAL 0x5a5aa5a5
+#define AO_BOOT_CHECK  0xc3c33c3c
+
+struct ao_boot {
+       uint32_t        *base;
+       uint32_t        signal;
+       uint32_t        check;
+};
+
+static struct ao_boot __attribute__ ((section(".boot"))) ao_boot;
+       
+int
+ao_boot_check_chain(void)
+{
+       if (ao_boot.signal == AO_BOOT_SIGNAL && ao_boot.check == AO_BOOT_CHECK) {
+               ao_boot.signal = 0;
+               ao_boot.check = 0;
+               if (ao_boot.base == 0)
+                       return 0;
+               ao_boot_chain(ao_boot.base);
+       }
+       return 1;
+}
+
+void
+ao_boot_reboot(uint32_t *base)
+{
+       ao_boot.base = base;
+       ao_boot.signal = AO_BOOT_SIGNAL;
+       ao_boot.check = AO_BOOT_CHECK;
+       ao_arch_reboot();
+}
diff --git a/src/lpc/ao_boot_pin.c b/src/lpc/ao_boot_pin.c
new file mode 100644 (file)
index 0000000..51ecc0a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_boot.h>
+#include <ao_exti.h>
+
+void
+ao_boot_check_pin(void)
+{
+       uint16_t v;
+
+       /* Enable power interface clock */
+//     stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
+       
+       /* Enable the input pin */
+       ao_enable_input(AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN,
+                       AO_BOOT_APPLICATION_MODE);
+
+       for (v = 0; v < 100; v++)
+               ao_arch_nop();
+
+       /* Read the value */
+       v = ao_gpio_get(AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, AO_BOOT_APPLICATION);
+
+       /* Reset the chip to turn off the port and the power interface clock */
+       ao_gpio_set_mode(AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, 0);
+       ao_disable_port(AO_BOOT_APPLICATION_GPIO);
+//     stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_PWREN);
+       if (v == AO_BOOT_APPLICATION_VALUE)
+               ao_boot_chain(AO_BOOT_APPLICATION_BASE);
+}
diff --git a/src/lpc/ao_flash.h b/src/lpc/ao_flash.h
new file mode 100644 (file)
index 0000000..aaf66b3
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_FLASH_H_
+#define _AO_FLASH_H_
+
+uint32_t
+ao_flash_erase_page(uint8_t *page);
+
+uint32_t
+ao_flash_page(uint8_t *page, uint8_t *src);
+
+uint32_t
+ao_lpc_read_part_id(void);
+
+#endif /* _AO_FLASH_H_ */
diff --git a/src/lpc/ao_flash_loader_lpc.c b/src/lpc/ao_flash_loader_lpc.c
new file mode 100644 (file)
index 0000000..2ab548c
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include <ao_exti.h>
+#include <ao_boot.h>
+#include <ao_flash_task.h>
+
+int
+main(void)
+{
+       ao_clock_init();
+
+       ao_usb_init();
+
+       ao_flash_task();
+       return 0;
+}
diff --git a/src/lpc/ao_flash_lpc_pins.h b/src/lpc/ao_flash_lpc_pins.h
new file mode 100644 (file)
index 0000000..e2243d5
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_FLASH_LPC_PINS_H_
+#define _AO_FLASH_LPC_PINS_H_
+
+#include <ao_flash_pins.h>
+
+/* Crystal on the board */
+#define AO_LPC_CLKIN   12000000
+
+/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */
+#define AO_LPC_CLKOUT  48000000
+
+/* System clock frequency */
+#define AO_LPC_SYSCLK  24000000
+
+#endif /* _AO_FLASH_STM_PINS_H_ */
index b5e67007f0919458480f378438a6a70810583b97..c4dc786760b460f17bd8f20a9100e36cba7b0652 100644 (file)
 
 #include <ao.h>
 #include <string.h>
+#include <ao_boot.h>
+
+#ifndef IS_FLASH_LOADER
+#error Should define IS_FLASH_LOADER
+#define IS_FLASH_LOADER        0
+#endif
+
+#if !IS_FLASH_LOADER
+#define RELOCATE_INTERRUPT     1
+#endif
 
 extern void main(void);
 extern char __stack__;
 extern char __text_start__, __text_end__;
 extern char __data_start__, __data_end__;
 extern char __bss_start__, __bss_end__;
+#if RELOCATE_INTERRUPT
+extern char __interrupt_rom__, __interrupt_start__, __interrupt_end__;
+#endif
 
 /* Interrupt functions */
 
@@ -35,10 +48,18 @@ void lpc_ignore_isr(void)
 {
 }
 
-int x;
-
 void start(void) {
-       x = 0;
+#ifdef AO_BOOT_CHAIN
+       if (ao_boot_check_chain()) {
+#ifdef AO_BOOT_PIN
+               ao_boot_check_pin();
+#endif
+       }
+#endif
+#if RELOCATE_INTERRUPT
+       memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__);
+       lpc_scb.sysmemremap = LPC_SCB_SYSMEMREMAP_MAP_RAM << LPC_SCB_SYSMEMREMAP_MAP;
+#endif
        memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);
        memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
        main();
index c3587698e1d26f55ac1b7b583b2ab76f7707b6ed..a889137cbb7a4e1f84437f601d76e78f8cc22ce8 100644 (file)
@@ -42,7 +42,7 @@ static uint8_t        spi_dev_null;
                        /* recv a byte */                               \
                        get lpc_ssp->dr;                                \
                }                                                       \
-       } while (0);
+       } while (0)
 
 void
 ao_spi_send(void *block, uint16_t len, uint8_t id)
index 51835baaa76310f94ec1381541db33e65987f210..44fb410e7f522b642d1a68f965f46681690a3d74 100644 (file)
@@ -100,18 +100,33 @@ ao_clock_init(void)
                                 (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO) |
                                 (1 << LPC_SCB_SYSAHBCLKCTRL_IOCON));
                                 
+       /* Enable the brown-out detection at the highest voltage to
+        * make sure the flash part remains happy
+        */
+
+       lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_BOD_PD);
+       lpc_scb.bodctrl = ((LPC_SCB_BOD_BODRSTLEV_2_63 << LPC_SCB_BOD_BODRSTLEV) |
+                          (LPC_SCB_BOD_BODINTVAL_RESERVED << LPC_SCB_BOD_BODINTVAL) |
+                          (1 << LPC_SCB_BOD_BODRSTENA));
+
        /* Turn the IRC clock back on */
        lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD);
        ao_clock_delay();
        
        /* Switch to the IRC clock */
        lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL;
-       lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA);
        lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA);
        lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA);
        while (!(lpc_scb.mainclkuen & (1 << LPC_SCB_MAINCLKUEN_ENA)))
                ;
        
+       /* Switch USB to the main clock */
+       lpc_scb.usbclksel = (LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK << LPC_SCB_USBCLKSEL_SEL);
+       lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA);
+       lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA);
+       while (!(lpc_scb.usbclkuen & (1 << LPC_SCB_USBCLKUEN_ENA)))
+               ;
+       
        /* Find a PLL post divider ratio that gets the FCCO in range */
        for (p = 0; p < 4; p++)
                if (AO_LPC_CLKOUT << (1 + p) >= AO_LPC_FCCO_MIN)
@@ -177,4 +192,22 @@ ao_clock_init(void)
        lpc_scb.ssp1clkdiv = 0;
        lpc_scb.usbclkdiv = 0;
        lpc_scb.clkoutdiv = 0;
+
+       /* Switch USB PLL source to system osc so we can power down the IRC */
+       lpc_scb.usbpllclksel = (LPC_SCB_USBPLLCLKSEL_SEL_SYSOSC << LPC_SCB_USBPLLCLKSEL_SEL);
+       lpc_scb.usbpllclkuen = (0 << LPC_SCB_USBPLLCLKUEN_ENA);
+       lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA);
+       while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA)))
+               ;
+       
+       /* Power down everything we don't need */
+       lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) |
+                           (1 << LPC_SCB_PDRUNCFG_IRC_PD) |
+                           (0 << LPC_SCB_PDRUNCFG_BOD_PD) |
+                           (1 << LPC_SCB_PDRUNCFG_ADC_PD) |
+                           (1 << LPC_SCB_PDRUNCFG_WDTOSC_PD) |
+                           (1 << LPC_SCB_PDRUNCFG_USBPLL_PD) |
+                           (1 << LPC_SCB_PDRUNCFG_USBPAD_PD) |
+                           (1 << 11) |
+                           (7 << 13));
 }
index aac0df04a8956f5b485dfcc9940ac4814fe571ef..144d10752b3ba2eb8642c1173586b4bb0eac71db 100644 (file)
 #include "ao_usb.h"
 #include "ao_product.h"
 
+#ifndef USE_USB_STDIO
+#define USE_USB_STDIO  1
+#endif
+
+#if USE_USB_STDIO
+#define AO_USB_OUT_SLEEP_ADDR  (&ao_stdin_ready)
+#else
+#define AO_USB_OUT_SLEEP_ADDR  (&ao_usb_out_avail)
+#endif
+
 #define USB_DEBUG      0
 #define USB_DEBUG_DATA 0
 #define USB_ECHO       0
@@ -35,8 +45,6 @@
 #define debug_data(format, args...)
 #endif
 
-struct ao_task ao_usb_task;
-
 struct ao_usb_setup {
        uint8_t         dir_type_recip;
        uint8_t         request;
@@ -654,7 +662,7 @@ lpc_usb_irq_isr(void)
                _rx_dbg1("RX ISR", *ao_usb_epn_out(AO_USB_OUT_EP));
                ao_usb_out_avail = 1;
                _rx_dbg0("out avail set");
-               ao_wakeup(&ao_stdin_ready);
+               ao_wakeup(AO_USB_OUT_SLEEP_ADDR)
                _rx_dbg0("stdin awoken");
        }
 
@@ -813,7 +821,7 @@ ao_usb_getchar(void)
 
        ao_arch_block_interrupts();
        while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN)
-               ao_sleep(&ao_stdin_ready);
+               ao_sleep(AO_USB_OUT_SLEEP_ADDR);
        ao_arch_release_interrupts();
        return c;
 }
@@ -823,6 +831,9 @@ ao_usb_disable(void)
 {
        ao_arch_block_interrupts();
 
+#if HAS_USB_PULLUP
+       ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 0);
+#endif
        /* Disable interrupts */
        lpc_usb.inten = 0;
 
@@ -834,8 +845,9 @@ ao_usb_disable(void)
        /* Turn off USB clock */
        lpc_scb.usbclkdiv = 0;
 
-       /* Disable USB PHY */
-       lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_USBPAD_PD);
+       /* Disable USB PHY and PLL */
+       lpc_scb.pdruncfg |= ((1 << LPC_SCB_PDRUNCFG_USBPAD_PD) |
+                            (1 << LPC_SCB_PDRUNCFG_USBPLL_PD));
 
        /* Disable USB registers and RAM */
        lpc_scb.sysahbclkctrl &= ~((1 << LPC_SCB_SYSAHBCLKCTRL_USB) |
@@ -877,7 +889,6 @@ ao_usb_enable(void)
        lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPLL_PD);
 
        lpc_scb.usbpllclksel = (LPC_SCB_SYSPLLCLKSEL_SEL_SYSOSC << LPC_SCB_SYSPLLCLKSEL_SEL);
-       lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA);
        lpc_scb.usbpllclkuen = (0 << LPC_SCB_USBPLLCLKUEN_ENA);
        lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA);
        while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA)))
@@ -887,6 +898,10 @@ ao_usb_enable(void)
                ;
 
        lpc_scb.usbclksel = 0;
+       lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA);
+       lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA);
+       while (!(lpc_scb.usbclkuen & (1 << LPC_SCB_USBCLKUEN_ENA)))
+               ;
 
        /* Turn on USB clock, use 48MHz clock unchanged */
        lpc_scb.usbclkdiv = 1;
@@ -921,6 +936,10 @@ ao_usb_enable(void)
        for (t = 0; t < 1000; t++)
                ao_arch_nop();
 
+#if HAS_USB_PULLUP
+       ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 1);
+#endif
+
        ao_usb_set_ep0();
 }
 
@@ -957,6 +976,10 @@ __code struct ao_cmds ao_usb_cmds[] = {
 void
 ao_usb_init(void)
 {
+#if HAS_USB_PULLUP
+       ao_enable_output(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 0);
+#endif
+
        ao_usb_enable();
 
        debug ("ao_usb_init\n");
@@ -966,7 +989,7 @@ ao_usb_init(void)
 #if USB_DEBUG
        ao_cmd_register(&ao_usb_cmds[0]);
 #endif
-#if !USB_ECHO
+#if USE_USB_STDIO
        ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush);
 #endif
 }
index 49034c1c564e71107ff5586c5acdbe74fb3c621c..3300c86f1d942f9a9ea03e47b70cd39cee4882ee 100644 (file)
@@ -486,6 +486,11 @@ struct lpc_scb {
 
 extern struct lpc_scb lpc_scb;
 
+#define LPC_SCB_SYSMEMREMAP_MAP                0
+# define LPC_SCB_SYSMEMREMAP_MAP_BOOT_LOADER   0
+# define LPC_SCB_SYSMEMREMAP_MAP_RAM           1
+# define LPC_SCB_SYSMEMREMAP_MAP_FLASH         2
+
 #define LPC_SCB_PRESETCTRL_SSP0_RST_N  0
 #define LPC_SCB_PRESETCTRL_I2C_RST_N   1
 #define LPC_SCB_PRESETCTRL_SSP1_RST_N  2
@@ -609,6 +614,18 @@ extern struct lpc_scb lpc_scb;
 
 #define LPC_SCB_CLKOUTUEN_ENA          0
 
+#define LPC_SCB_BOD_BODRSTLEV          0
+# define LPC_SCB_BOD_BODRSTLEV_1_46            0
+# define LPC_SCB_BOD_BODRSTLEV_2_06            1
+# define LPC_SCB_BOD_BODRSTLEV_2_35            2
+# define LPC_SCB_BOD_BODRSTLEV_2_63            3
+#define LPC_SCB_BOD_BODINTVAL          2
+# define LPC_SCB_BOD_BODINTVAL_RESERVED                0
+# define LPC_SCB_BOD_BODINTVAL_2_22            1
+# define LPC_SCB_BOD_BODINTVAL_2_52            2
+# define LPC_SCB_BOD_BODINTVAL_2_80            3
+#define LPC_SCB_BOD_BODRSTENA          4
+
 #define LPC_SCB_PDRUNCFG_IRCOUT_PD     0
 #define LPC_SCB_PDRUNCFG_IRC_PD                1
 #define LPC_SCB_PDRUNCFG_FLASH_PD      2
@@ -1002,12 +1019,12 @@ extern struct lpc_nvic lpc_nvic;
 
 static inline void
 lpc_nvic_set_enable(int irq) {
-       lpc_nvic.iser |= (1 << irq);
+       lpc_nvic.iser = (1 << irq);
 }
 
 static inline void
 lpc_nvic_clear_enable(int irq) {
-       lpc_nvic.icer |= (1 << irq);
+       lpc_nvic.icer = (1 << irq);
 }
 
 static inline int
@@ -1169,6 +1186,13 @@ extern struct lpc_adc lpc_adc;
 #define  LPC_ADC_CR_CLKS_6             5
 #define  LPC_ADC_CR_CLKS_5             6
 #define  LPC_ADC_CR_CLKS_4             7
+#define LPC_ADC_CR_START       24
+#define  LPC_ADC_CR_START_NONE         0
+#define  LPC_ADC_CR_START_NOW          1
+
+#define LPC_ADC_GDR_CHN                        24
+#define LPC_ADC_GDR_OVERRUN            30
+#define LPC_ADC_GDR_DONE               31
 
 #define LPC_ADC_INTEN_ADINTEN  0
 #define LPC_ADC_INTEN_ADGINTEN 8
index b774df6d3668a68a44b8a55915be530a7eadaea3..439ba75cecc8fe04fad50dc61e3cc1f7905d08b1 100644 (file)
@@ -37,4 +37,6 @@
 #define AO_BOOT_CHAIN          1
 #define AO_BOOT_PIN            1
 
+#define IS_FLASH_LOADER                1
+
 #endif /* _AO_FLASH_PINS_H_ */
index fdc4d0aa5ad3b9bbd059adecc5c1476558892337..4cfbf75fde3d15c38b7b8ab0809bb9a85abfc3d8 100644 (file)
@@ -73,7 +73,7 @@ static void
 ao_block_erase(void)
 {
        uint32_t        addr = ao_get_hex32();
-       uint32_t        *p = (uint32_t *) addr;
+       void            *p = (void *) addr;
 
        ao_flash_erase_page(p);
 }
@@ -82,11 +82,8 @@ static void
 ao_block_write(void)
 {
        uint32_t        addr = ao_get_hex32();
-       uint32_t        *p = (uint32_t *) addr;
-       union {
-               uint8_t         data8[256];
-               uint32_t        data32[64];
-       } u;
+       void            *p = (void *) addr;
+       uint8_t         data[256];
        uint16_t        i;
 
        if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) {
@@ -94,8 +91,8 @@ ao_block_write(void)
                return;
        }
        for (i = 0; i < 256; i++)
-               u.data8[i] = ao_usb_getchar();
-       ao_flash_page(p, u.data32);
+               data[i] = ao_usb_getchar();
+       ao_flash_page(p, (void *) data);
 }
 
 static void
index 774d59f45631ba155424df7a93f34ab48af58a76..f7a3ff2cea2dc40b7e31866da843d139aac494f7 100644 (file)
 
 #define AO_LED_CONTINUITY(c)   (1 << ((c) + 2))
 #define AO_LED_CONTINUITY_MASK (0xc)
-#define AO_LED_RX              0x10
-#define AO_LED_TX              0x20
-#define AO_LED_ARMED           0x40
-#define AO_LED_POWER           0x80
-
-#define AO_LED_RED             AO_LED_TX
-#define AO_LED_GREEN           AO_LED_RX
+#define AO_LED_ARMED           0x10
+#define AO_LED_RED             0x20
+#define AO_LED_AMBER           0x40
+#define AO_LED_GREEN           0x80
 
 #define LEDS_AVAILABLE         (0xff)
 #define HAS_EXTERNAL_TEMP      0
index f40507221d8b0563ce25dbef593a9ebb10975893..96e6b066081e47801310c428f644efe86ad700da 100644 (file)
 
 #define AO_LED_CONTINUITY(c)   (1 << (c))
 #define AO_LED_CONTINUITY_MASK (0xf)
-#define AO_LED_RX              0x10
-#define AO_LED_TX              0x20
-#define AO_LED_ARMED           0x40
-#define AO_LED_POWER           0x80
-
-#define AO_LED_RED             AO_LED_TX
-#define AO_LED_GREEN           AO_LED_RX
+#define AO_LED_ARMED           0x10
+#define AO_LED_RED             0x20
+#define AO_LED_AMBER           0x40
+#define AO_LED_GREEN           0x80
 
 #define LEDS_AVAILABLE         (0xff)
 #define HAS_EXTERNAL_TEMP      0
index 3c9ac9c6f1156ca9a2a75d6403602405ea5db3de..75b1f8485684dbf4f2409ea582479094f510f0aa 100644 (file)
@@ -69,7 +69,7 @@ ao_micropeak_test: ao_micropeak_test.c ao_microflight.c ao_kalman.h
        cc $(CFLAGS) -o $@ ao_micropeak_test.c -lm
 
 ao_fat_test: ao_fat_test.c ao_fat.c ao_bufio.c
-       cc $(CFLAGS) -o $@ ao_fat_test.c -lssl
+       cc $(CFLAGS) -o $@ ao_fat_test.c -lssl -lcrypto
 
 ao_aes_test: ao_aes_test.c ao_aes.c ao_aes_tables.c
        cc $(CFLAGS) -o $@ ao_aes_test.c