Workstation 40 - A 40 pin DIP base board for the ESP210 module

From Electronic Sweet Peas
Jump to: navigation, search

Introduction

Workstation-1-iso.pngWorkstation-2-iso.png

Now available for pre order in our new web shop

This workstation board adds both analogue and digital IO to your system and makes your node.IT stack look like a 40pin microcontroller. The ESP210 module mounts on stacking connectors, on top to the left of the workstation board. This allows the original ESP210 signals to pass through the stacking connector down to whatever it is that you are connecting the system to.

The rest of the pins on the Workstation40 board adds functionality to your system through the built in Cortex-M0 microcontroller and the I2C port expander. Communication with the new peripherals is done through a I2C serial interface.

The Board

WorkStation40.png

The board is based on an Atmel SAMD10D Cortex-M0 microcontroller (U2) and a NXP PCA9554 I2C port expander (U3), both working in slave mode and connected to the same I2C bus towards the ESP210

The SAMD10D microcontroller features an I2C bootloader that allows the controller to be flashed with any custom firmware making it possible to use the Workstation40 board as a smart peripheral to the ESP210. By default the device is loaded with a firmware that makes the board look like a ADC/GPIO/Timer peripheral

Software

The board is shipped with an I2C boot loader which can be used to update the WorkStation firmware. More details on the boot loader will be available later on.

The WorkStation firmware is a simple I2C based message bridge that allows the Host (your ESP210) to read and write both registers and memory locations inside the SAMD10 processor. This exposes the entire SAMD10 processor to you and you can do whatever you like with it (well almost, more on the limitations later).

Flashing new fw to the WorkStation40 board

The WorkStation40 board comes with an I2C bootloader pre installed. This bootloader allows you to install new firmware on the built in microcontroller.

The following piece of code can be used to flash your new firmware.

/*
 * ----------------------------------------------------------------------------
 *            _____ _           _                   _
 *           | ____| | ___  ___| |_ _ __ ___  _ __ (_) ___
 *           |  _| | |/ _ \/ __| __| '__/ _ \| '_ \| |/ __|
 *           | |___| |  __/ (__| |_| | | (_) | | | | | (__
 *           |_____|_|\___|\___|\__|_|  \___/|_| |_|_|\___|
 *            ____                   _   ____
 *           / ___|_      _____  ___| |_|  _ \ ___  __ _ ___
 *           \___ \ \ /\ / / _ \/ _ \ __| |_) / _ \/ _` / __|
 *            ___) \ V  V /  __/  __/ |_|  __/  __/ (_| \__ \
 *           |____/ \_/\_/ \___|\___|\__|_|   \___|\__,_|___/
 *
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <pontus@sweetpeas.se> wrote this file. As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return - Pontus Oldberg
 * ----------------------------------------------------------------------------
 */
 
#include <twi.h>
#include <Wire.h>
#include "fw.h"
 
#define SCL_PIN      14
#define SDA_PIN      2
 
const uint8_t slaveAdr = 0x15;
 
// This is the instance of TwoWire that we will use.
TwoWire wire = TwoWire(256);
 
void setup() {
  // put your setup code here, to run once:
  wire.begin(SDA_PIN, SCL_PIN);
  Serial.begin(115200);
  pinMode(12, OUTPUT);
  digitalWrite(12, LOW);
 
  Serial.println(F("\nWorkStation40 Flash Utility !"));
  Serial.println(F("Waiting for user to press a character to start flashing !"));
  while (!Serial.available());
  Serial.read();
}
 
void print_i2c_status(int status)
{
   switch (status) {
    case 0:
      Serial.println(F("Successfull transmission !"));
      break;
    case 1:
      Serial.println(F("data too long to fit in transmit buffer"));
      break;
    case 2:
      Serial.println(F("received NACK on transmit of address"));
      break;
    case 3:
      Serial.println(F("received NACK on transmit of data"));
      break;
    case 4:
      Serial.println(F("other error"));
      break;
    default:
      Serial.println(F("WTF, I have no clue what happened !"));
      break;     
  }
}
 
int send_length(uint32_t length)
{
  wire.beginTransmission(slaveAdr);
  wire.write((length >> 24) & 0xff);
  wire.write((length >> 16) & 0xff);  
  wire.write((length >> 8) & 0xff);  
  wire.write(length & 0xff);  
  return wire.endTransmission(true);  
}
 
uint16_t get_page_size(void) 
{
  uint16_t page_size = 0;
  int i;
 
  wire.requestFrom(slaveAdr, (uint8_t)2);
  while (wire.available() < 2);
  for (i=0;i<2;i++) {
    page_size = (page_size << 8) | wire.read();
  }
  return page_size;
}
 
/*
 * Wait for ack from the slave
 */
int wait_for_ack()
{
  // Allow for the flash to be programmed
  wire.requestFrom(slaveAdr, (uint8_t)1);
  while (wire.available() < 1);
  if (wire.read() == 's') {
    Serial.write('.');
    return 0;
  }
  return 1;
}
 
/*
 * This functions sends the fw in chunks as reported by the slave.
 *
 */
int send_data(unsigned char *buf, int len, int page_size)
{
  int er;
 
  do {
    er = twi_writeTo(slaveAdr, buf, min(page_size, len), true);
    buf += min(page_size, len);
    len -= min(page_size, len);
    if (0 != er && 3 != er) {
      Serial.println(F("Fault while transmitting data !"));
      return er;
    }
    delay(15);
    er = wait_for_ack();
    if (er) {
      Serial.println(F("No ack received from slave !"));
      return er+10;
    }
  } while (len);
  return 0;
}
 
void loop() 
{
  static boolean finished = false;
  int cntr = 1;
  int status = 1;
  uint32_t dataLength = fw_bin_len;
  uint16_t page_size;
 
  if (!finished) {
    do {
      Serial.print(F("Sending 4 bytes data length, iteration "));
      Serial.println(cntr++, DEC);
      status = send_length(dataLength);
      if (status && cntr != 11) delay(5000);
    } while (status && cntr != 11);
    if (cntr == 11) {
      Serial.println(F("To many retries, stopping execution !"));
      finished = true;
      return;
    }
    Serial.println(F("Boot device found. "));
    Serial.print(F("Data Length ("));
    Serial.print(dataLength, DEC);
    Serial.println(F(" bytes) sent."));
 
    page_size = get_page_size();
    Serial.print(F("Page length = "));
    Serial.print(page_size, DEC);
    Serial.println(F(" bytes"));
 
    Serial.println(F("Flashing new firmware !"));
    int err = send_data(fw_bin, fw_bin_len, page_size);
    if (err) {
      Serial.print(F("\nFailed to flash image, error: "));
      Serial.println(err);
    } else {
      Serial.println(F("\nFlash successfull !"));
    }
    Serial.println(F("Stopping !"));
    finished = true;
  }  
}

Downloads

Tips, Tricks and useful links

Nothing yet