MediaTek-Labs / Arduino-Add-On-for-LinkIt-SDK

Arduino board support package for LinkIt 7697
https://docs.labs.mediatek.com/resource/linkit7697-arduino/en
34 stars 33 forks source link

Pin/port/register macros not defined in cores/Arduino.h #70

Open oesterle opened 7 years ago

oesterle commented 7 years ago

Pin/port/register macros not defined in cores/Arduino.h, including: digitalPinToPort portOutputRegister digitalPinToBitMask

Found while trying to use Adafruit_SSD1351 OLED display library: https://github.com/adafruit/Adafruit-SSD1351-library

pablosun commented 7 years ago

Good suggestions here, will see if we can implement those internal APIs here. One questions though - Is the digitalWrite() API too slow for your use case here?

pablosun commented 7 years ago

@oesterle it seems that portOutputRegiter and digitalPinToBitMask are not compatible to MT7697. It is possible to expose underlying HW registers, but the usage will be different from AVR Arduinos.

HW Register Design Differences

The AVR architectures uses same HW register for "set" and "unset" pin state:

reg= portOutputRegister(digitalPinToPort(PIN));
pinMask = digitalPinToBitMask(PIN);

// this unset PIN output to LOW
*reg &= ~pinMask ; 

// this set PIN output to HIGH
*reg |= pinMask ;     

However, the peripheral system of MT7697 separates "set" and "unset" into two different HW registers:


regSet= portOutputRegisterSet(digitalPinToPort(PIN));
regUnset = portOutputRegisterSet(digitalPinToPort(PIN));

// Set PIN to HIGH
*regSet = pinMask;

// Unset PIN to LOW
*regUnset = pinMask ;

Note: We can refer to the MT76x7 Reference Manual and see the design of following HW registers:

Speed gains of HW Regsiter

We can get around 10x gains by replacing digitalWrite calls with low-level HW register writes.

A simple digitalWrite that flips PIN 2 as show below:

#include <FreeRTOS.h>
#include <task.h>
void setup() {
  pinMode(2, OUTPUT);
  taskDISABLE_INTERRUPTS();
}

void loop() {
  while(1){
    digitalWrite(2, 1);
    digitalWrite(2, 0);
  }
}

Generates a waveform around 1.3MHz default

If we replace the digitalWrite calls to direct HW register right:

#include <FreeRTOS.h>
#include <task.h>
void setup() {
  pinMode(2, OUTPUT);
  taskDISABLE_INTERRUPTS();
}

// Register-based GPIO write
#define IOT_GPIO_AON_BASE           (0x8300B000)
#define IOT_GPIO_DOUT1              (0x60)                 
#define IOT_GPIO_DOUT1_SET          (IOT_GPIO_DOUT1 + 0x04)
#define IOT_GPIO_DOUT1_RESET        (IOT_GPIO_DOUT1 + 0x08)
#define IOT_GPIO_DOUT2              (0x70)                 
#define IOT_GPIO_DOUT2_SET          (IOT_GPIO_DOUT2 + 0x04)
#define IOT_GPIO_DOUT2_RESET        (IOT_GPIO_DOUT2 + 0x08)
#define IOT_GPIO_DOUT3              (0x80)                 
#define IOT_GPIO_DOUT3_SET          (IOT_GPIO_DOUT3 + 0x04)
#define IOT_GPIO_DOUT3_RESET        (IOT_GPIO_DOUT3 + 0x08)
#define DRV_WriteReg32(addr,data)     ((*(volatile unsigned int *)(addr)) = (unsigned int)(data))

void loop() {
  while(1){
    DRV_WriteReg32(IOT_GPIO_AON_BASE + IOT_GPIO_DOUT1_SET, (1 << 0));
    DRV_WriteReg32(IOT_GPIO_AON_BASE + IOT_GPIO_DOUT1_RESET, (1 << 0));
  }
}

we can generate a waveform around 20MHz, which is an improvement. default

oesterle commented 7 years ago

digitalWrite is probably fast enough, for now. I'm much more concerned with being able to use common Arduino libraries with MT7697. I'm using LinkIt 7697 partly because ESP32 Arduino doesn't support BLE, yet (after almost a year of being on the market).

Whatever you can do to make existing SPI & I2C code "just work" on LinkIt 7697 will mean that I use it in more projects.

Thank you, Pablo!