Open oesterle opened 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?
@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.
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:
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
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.
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!
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