2017-07-18 18:29:06 -05:00
|
|
|
/**
|
|
|
|
* Marlin 3D Printer Firmware
|
2020-02-03 08:00:57 -06:00
|
|
|
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
2017-07-18 18:29:06 -05:00
|
|
|
*
|
|
|
|
* Based on Sprinter and grbl.
|
2019-06-27 23:57:50 -05:00
|
|
|
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
2017-07-18 18:29:06 -05:00
|
|
|
*
|
|
|
|
* 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, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* 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
|
2020-07-22 22:20:14 -05:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2017-07-18 18:29:06 -05:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Software SPI functions originally from Arduino Sd2Card Library
|
2019-06-27 23:57:50 -05:00
|
|
|
* Copyright (c) 2009 by William Greiman
|
2017-12-20 23:35:49 -06:00
|
|
|
*
|
|
|
|
* Completely rewritten and tuned by Eduardo José Tagle in 2017/2018
|
|
|
|
* in ARM thumb2 inline assembler and tuned for maximum speed and performance
|
|
|
|
* allowing SPI clocks of up to 12 Mhz to increase SD card read/write performance
|
2017-07-18 18:29:06 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Description: HAL for Arduino Due and compatible (SAM3X8E)
|
|
|
|
*
|
|
|
|
* For ARDUINO_ARCH_SAM
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef ARDUINO_ARCH_SAM
|
|
|
|
|
2017-09-06 06:28:32 -05:00
|
|
|
#include "../../inc/MarlinConfig.h"
|
2018-08-14 03:28:52 -05:00
|
|
|
#include "../shared/Delay.h"
|
2017-07-18 18:29:06 -05:00
|
|
|
|
2019-07-09 22:30:06 -05:00
|
|
|
// ------------------------
|
2017-07-18 18:29:06 -05:00
|
|
|
// Public functions
|
2019-07-09 22:30:06 -05:00
|
|
|
// ------------------------
|
2017-07-18 18:29:06 -05:00
|
|
|
|
2019-04-21 20:48:53 -05:00
|
|
|
#if EITHER(DUE_SOFTWARE_SPI, FORCE_SOFT_SPI)
|
2018-03-10 22:46:32 -06:00
|
|
|
|
2019-07-09 22:30:06 -05:00
|
|
|
// ------------------------
|
|
|
|
// Software SPI
|
|
|
|
// ------------------------
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
|
2018-05-12 08:34:04 -05:00
|
|
|
// Make sure GCC optimizes this file.
|
|
|
|
// Note that this line triggers a bug in GCC which is fixed by casting.
|
|
|
|
// See the note below.
|
2017-12-20 23:35:49 -06:00
|
|
|
#pragma GCC optimize (3)
|
|
|
|
|
2018-05-12 08:34:04 -05:00
|
|
|
typedef uint8_t (*pfnSpiTransfer)(uint8_t b);
|
2017-12-28 00:32:46 -06:00
|
|
|
typedef void (*pfnSpiRxBlock)(uint8_t* buf, uint32_t nbyte);
|
|
|
|
typedef void (*pfnSpiTxBlock)(const uint8_t* buf, uint32_t nbyte);
|
|
|
|
|
2017-12-20 23:35:49 -06:00
|
|
|
/* ---------------- Macros to be able to access definitions from asm */
|
|
|
|
#define _PORT(IO) DIO ## IO ## _WPORT
|
|
|
|
#define _PIN_MASK(IO) MASK(DIO ## IO ## _PIN)
|
|
|
|
#define _PIN_SHIFT(IO) DIO ## IO ## _PIN
|
|
|
|
#define PORT(IO) _PORT(IO)
|
|
|
|
#define PIN_MASK(IO) _PIN_MASK(IO)
|
|
|
|
#define PIN_SHIFT(IO) _PIN_SHIFT(IO)
|
|
|
|
|
|
|
|
// run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
|
|
|
|
static uint8_t spiTransferTx0(uint8_t bout) { // using Mode 0
|
2018-11-04 16:17:13 -06:00
|
|
|
uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
|
|
|
|
uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
|
|
|
|
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
|
|
|
uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
|
|
|
uint32_t idx = 0;
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Negate bout, as the assembler requires a negated value */
|
|
|
|
bout = ~bout;
|
|
|
|
|
|
|
|
/* The software SPI routine */
|
|
|
|
__asm__ __volatile__(
|
2018-05-11 00:27:36 -05:00
|
|
|
A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 7 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("ubfx %[idx],%[txval],#7,#1") /* Place bit 7 in bit 0 of idx*/
|
2017-12-20 23:35:49 -06:00
|
|
|
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#6,#1") /* Place bit 6 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 6 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#5,#1") /* Place bit 5 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 5 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#4,#1") /* Place bit 4 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 4 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#3,#1") /* Place bit 3 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 3 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#2,#1") /* Place bit 2 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 2 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#1,#1") /* Place bit 1 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 1 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#0,#1") /* Place bit 0 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 0 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("nop") /* Result will be 0 */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
2017-12-28 00:32:46 -06:00
|
|
|
: [idx]"+r"( idx )
|
|
|
|
: [txval]"r"( bout ) ,
|
|
|
|
[mosi_mask]"r"( MOSI_MASK ),
|
|
|
|
[mosi_port]"r"( MOSI_PORT_PLUS30 ),
|
|
|
|
[sck_mask]"r"( SCK_MASK ),
|
|
|
|
[sck_port]"r"( SCK_PORT_PLUS30 )
|
2017-12-20 23:35:49 -06:00
|
|
|
: "cc"
|
|
|
|
);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-05-12 08:34:04 -05:00
|
|
|
// Calculates the bit band alias address and returns a pointer address to word.
|
|
|
|
// addr: The byte address of bitbanding bit.
|
|
|
|
// bit: The bit position of bitbanding bit.
|
|
|
|
#define BITBAND_ADDRESS(addr, bit) \
|
2017-12-28 00:32:46 -06:00
|
|
|
(((uint32_t)(addr) & 0xF0000000) + 0x02000000 + ((uint32_t)(addr)&0xFFFFF)*32 + (bit)*4)
|
|
|
|
|
2017-12-20 23:35:49 -06:00
|
|
|
// run at ~8 .. ~10Mhz - Rx version (Tx line not altered)
|
2019-09-30 21:44:07 -05:00
|
|
|
static uint8_t spiTransferRx0(uint8_t) { // using Mode 0
|
2018-11-04 16:17:13 -06:00
|
|
|
uint32_t bin = 0;
|
|
|
|
uint32_t work = 0;
|
|
|
|
uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
|
|
|
|
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
|
|
|
uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* The software SPI routine */
|
|
|
|
__asm__ __volatile__(
|
2018-05-11 00:27:36 -05:00
|
|
|
A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 7 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#7,#1") /* Store read bit as the bit 7 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 6 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#6,#1") /* Store read bit as the bit 6 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 5 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#5,#1") /* Store read bit as the bit 5 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 4 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#4,#1") /* Store read bit as the bit 4 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 3 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#3,#1") /* Store read bit as the bit 3 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 2 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#2,#1") /* Store read bit as the bit 2 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 1 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#1,#1") /* Store read bit as the bit 1 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 0 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#0,#1") /* Store read bit as the bit 0 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
2017-12-28 00:32:46 -06:00
|
|
|
: [bin]"+r"(bin),
|
2017-12-20 23:35:49 -06:00
|
|
|
[work]"+r"(work)
|
2017-12-28 00:32:46 -06:00
|
|
|
: [bitband_miso_port]"r"( BITBAND_MISO_PORT ),
|
|
|
|
[sck_mask]"r"( SCK_MASK ),
|
|
|
|
[sck_port]"r"( SCK_PORT_PLUS30 )
|
2017-12-20 23:35:49 -06:00
|
|
|
: "cc"
|
|
|
|
);
|
|
|
|
|
2017-12-28 00:32:46 -06:00
|
|
|
return bin;
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// run at ~4Mhz
|
|
|
|
static uint8_t spiTransfer1(uint8_t b) { // using Mode 0
|
|
|
|
int bits = 8;
|
|
|
|
do {
|
|
|
|
WRITE(MOSI_PIN, b & 0x80);
|
2017-12-20 23:35:49 -06:00
|
|
|
b <<= 1; // little setup time
|
2017-07-18 18:29:06 -05:00
|
|
|
|
|
|
|
WRITE(SCK_PIN, HIGH);
|
2017-12-20 23:35:49 -06:00
|
|
|
DELAY_NS(125); // 10 cycles @ 84mhz
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
|
|
|
|
b |= (READ(MISO_PIN) != 0);
|
2017-07-18 18:29:06 -05:00
|
|
|
|
|
|
|
WRITE(SCK_PIN, LOW);
|
2017-12-20 23:35:49 -06:00
|
|
|
DELAY_NS(125); // 10 cycles @ 84mhz
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
} while (--bits);
|
2017-07-18 18:29:06 -05:00
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
// all the others
|
2020-01-08 20:00:06 -06:00
|
|
|
static uint32_t spiDelayCyclesX4 = (F_CPU) / 1000000; // 4µs => 125khz
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
|
|
|
|
static uint8_t spiTransferX(uint8_t b) { // using Mode 0
|
|
|
|
int bits = 8;
|
|
|
|
do {
|
|
|
|
WRITE(MOSI_PIN, b & 0x80);
|
|
|
|
b <<= 1; // little setup time
|
|
|
|
|
|
|
|
WRITE(SCK_PIN, HIGH);
|
|
|
|
__delay_4cycles(spiDelayCyclesX4);
|
|
|
|
|
|
|
|
b |= (READ(MISO_PIN) != 0);
|
|
|
|
|
|
|
|
WRITE(SCK_PIN, LOW);
|
|
|
|
__delay_4cycles(spiDelayCyclesX4);
|
|
|
|
} while (--bits);
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2017-12-28 00:32:46 -06:00
|
|
|
// Pointers to generic functions for byte transfers
|
2018-05-12 08:34:04 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Note: The cast is unnecessary, but without it, this file triggers a GCC 4.8.3-2014 bug.
|
|
|
|
* Later GCC versions do not have this problem, but at this time (May 2018) Arduino still
|
|
|
|
* uses that buggy and obsolete GCC version!!
|
|
|
|
*/
|
|
|
|
static pfnSpiTransfer spiTransferRx = (pfnSpiTransfer)spiTransferX;
|
|
|
|
static pfnSpiTransfer spiTransferTx = (pfnSpiTransfer)spiTransferX;
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
|
2017-12-28 00:32:46 -06:00
|
|
|
// Block transfers run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
|
|
|
|
static void spiTxBlock0(const uint8_t* ptr, uint32_t todo) {
|
2018-11-04 16:17:13 -06:00
|
|
|
uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
|
|
|
|
uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
|
|
|
|
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
|
|
|
uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
|
|
|
uint32_t work = 0;
|
|
|
|
uint32_t txval = 0;
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* The software SPI routine */
|
|
|
|
__asm__ __volatile__(
|
2018-05-11 00:27:36 -05:00
|
|
|
A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax
|
2017-12-28 00:32:46 -06:00
|
|
|
|
2018-05-08 05:10:27 -05:00
|
|
|
L("loop%=")
|
|
|
|
A("ldrb.w %[txval], [%[ptr]], #1") /* Load value to send, increment buffer */
|
|
|
|
A("mvn %[txval],%[txval]") /* Negate value */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 7 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("ubfx %[work],%[txval],#7,#1") /* Place bit 7 in bit 0 of work*/
|
2017-12-28 00:32:46 -06:00
|
|
|
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#6,#1") /* Place bit 6 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 6 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#5,#1") /* Place bit 5 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 5 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#4,#1") /* Place bit 4 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 4 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#3,#1") /* Place bit 3 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 3 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#2,#1") /* Place bit 2 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 2 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#1,#1") /* Place bit 1 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 1 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#0,#1") /* Place bit 0 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 0 */
|
2018-05-12 08:34:04 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("subs %[todo],#1") /* Decrement count of pending words to send, update status */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bne.n loop%=") /* Repeat until done */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
: [ptr]"+r" ( ptr ) ,
|
|
|
|
[todo]"+r" ( todo ) ,
|
|
|
|
[work]"+r"( work ) ,
|
|
|
|
[txval]"+r"( txval )
|
|
|
|
: [mosi_mask]"r"( MOSI_MASK ),
|
|
|
|
[mosi_port]"r"( MOSI_PORT_PLUS30 ),
|
|
|
|
[sck_mask]"r"( SCK_MASK ),
|
|
|
|
[sck_port]"r"( SCK_PORT_PLUS30 )
|
|
|
|
: "cc"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void spiRxBlock0(uint8_t* ptr, uint32_t todo) {
|
2018-11-04 16:17:13 -06:00
|
|
|
uint32_t bin = 0;
|
|
|
|
uint32_t work = 0;
|
|
|
|
uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
|
|
|
|
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
|
|
|
uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* The software SPI routine */
|
|
|
|
__asm__ __volatile__(
|
2018-05-11 00:27:36 -05:00
|
|
|
A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax
|
2017-12-28 00:32:46 -06:00
|
|
|
|
2018-05-08 05:10:27 -05:00
|
|
|
L("loop%=")
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 7 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#7,#1") /* Store read bit as the bit 7 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 6 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#6,#1") /* Store read bit as the bit 6 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 5 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#5,#1") /* Store read bit as the bit 5 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 4 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#4,#1") /* Store read bit as the bit 4 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 3 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#3,#1") /* Store read bit as the bit 3 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 2 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#2,#1") /* Store read bit as the bit 2 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 1 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#1,#1") /* Store read bit as the bit 1 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 0 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#0,#1") /* Store read bit as the bit 0 */
|
|
|
|
|
|
|
|
A("subs %[todo],#1") /* Decrement count of pending words to send, update status */
|
|
|
|
A("strb.w %[bin], [%[ptr]], #1") /* Store read value into buffer, increment buffer pointer */
|
|
|
|
A("bne.n loop%=") /* Repeat until done */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
: [ptr]"+r"(ptr),
|
|
|
|
[todo]"+r"(todo),
|
|
|
|
[bin]"+r"(bin),
|
|
|
|
[work]"+r"(work)
|
|
|
|
: [bitband_miso_port]"r"( BITBAND_MISO_PORT ),
|
|
|
|
[sck_mask]"r"( SCK_MASK ),
|
|
|
|
[sck_port]"r"( SCK_PORT_PLUS30 )
|
|
|
|
: "cc"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void spiTxBlockX(const uint8_t* buf, uint32_t todo) {
|
|
|
|
do {
|
2019-09-16 20:27:04 -05:00
|
|
|
(void)spiTransferTx(*buf++);
|
2017-12-28 00:32:46 -06:00
|
|
|
} while (--todo);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void spiRxBlockX(uint8_t* buf, uint32_t todo) {
|
|
|
|
do {
|
2018-04-04 20:13:27 -05:00
|
|
|
*buf++ = spiTransferRx(0xFF);
|
2017-12-28 00:32:46 -06:00
|
|
|
} while (--todo);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pointers to generic functions for block tranfers
|
2018-05-12 08:34:04 -05:00
|
|
|
static pfnSpiTxBlock spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
|
|
|
|
static pfnSpiRxBlock spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
|
2017-12-28 00:32:46 -06:00
|
|
|
|
2019-02-06 06:31:31 -06:00
|
|
|
#if MB(ALLIGATOR)
|
|
|
|
#define _SS_WRITE(S) WRITE(SS_PIN, S)
|
|
|
|
#else
|
|
|
|
#define _SS_WRITE(S) NOOP
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void spiBegin() {
|
|
|
|
SET_OUTPUT(SS_PIN);
|
|
|
|
_SS_WRITE(HIGH);
|
|
|
|
SET_OUTPUT(SCK_PIN);
|
|
|
|
SET_INPUT(MISO_PIN);
|
|
|
|
SET_OUTPUT(MOSI_PIN);
|
|
|
|
}
|
2018-03-10 22:46:32 -06:00
|
|
|
|
2019-02-06 06:31:31 -06:00
|
|
|
uint8_t spiRec() {
|
|
|
|
_SS_WRITE(LOW);
|
|
|
|
WRITE(MOSI_PIN, HIGH); // Output 1s 1
|
|
|
|
uint8_t b = spiTransferRx(0xFF);
|
|
|
|
_SS_WRITE(HIGH);
|
|
|
|
return b;
|
|
|
|
}
|
2018-03-10 22:46:32 -06:00
|
|
|
|
2019-02-06 06:31:31 -06:00
|
|
|
void spiRead(uint8_t* buf, uint16_t nbyte) {
|
|
|
|
if (nbyte) {
|
|
|
|
_SS_WRITE(LOW);
|
|
|
|
WRITE(MOSI_PIN, HIGH); // Output 1s 1
|
|
|
|
spiRxBlock(buf, nbyte);
|
|
|
|
_SS_WRITE(HIGH);
|
2018-03-10 22:46:32 -06:00
|
|
|
}
|
2019-02-06 06:31:31 -06:00
|
|
|
}
|
2018-03-10 22:46:32 -06:00
|
|
|
|
2019-02-06 06:31:31 -06:00
|
|
|
void spiSend(uint8_t b) {
|
|
|
|
_SS_WRITE(LOW);
|
|
|
|
(void)spiTransferTx(b);
|
|
|
|
_SS_WRITE(HIGH);
|
|
|
|
}
|
2018-03-11 10:28:46 -05:00
|
|
|
|
2019-02-06 06:31:31 -06:00
|
|
|
void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
|
|
|
_SS_WRITE(LOW);
|
|
|
|
(void)spiTransferTx(token);
|
|
|
|
spiTxBlock(buf, 512);
|
|
|
|
_SS_WRITE(HIGH);
|
2017-12-28 00:32:46 -06:00
|
|
|
}
|
|
|
|
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
/**
|
|
|
|
* spiRate should be
|
|
|
|
* 0 : 8 - 10 MHz
|
|
|
|
* 1 : 4 - 5 MHz
|
|
|
|
* 2 : 2 - 2.5 MHz
|
|
|
|
* 3 : 1 - 1.25 MHz
|
|
|
|
* 4 : 500 - 625 kHz
|
|
|
|
* 5 : 250 - 312 kHz
|
|
|
|
* 6 : 125 - 156 kHz
|
|
|
|
*/
|
2017-07-18 18:29:06 -05:00
|
|
|
void spiInit(uint8_t spiRate) {
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
switch (spiRate) {
|
|
|
|
case 0:
|
2018-05-12 08:34:04 -05:00
|
|
|
spiTransferTx = (pfnSpiTransfer)spiTransferTx0;
|
|
|
|
spiTransferRx = (pfnSpiTransfer)spiTransferRx0;
|
|
|
|
spiTxBlock = (pfnSpiTxBlock)spiTxBlock0;
|
|
|
|
spiRxBlock = (pfnSpiRxBlock)spiRxBlock0;
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
break;
|
|
|
|
case 1:
|
2018-05-12 08:34:04 -05:00
|
|
|
spiTransferTx = (pfnSpiTransfer)spiTransfer1;
|
|
|
|
spiTransferRx = (pfnSpiTransfer)spiTransfer1;
|
|
|
|
spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
|
|
|
|
spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
break;
|
|
|
|
default:
|
2019-02-06 06:31:31 -06:00
|
|
|
spiDelayCyclesX4 = ((F_CPU) / 1000000) >> (6 - spiRate);
|
2018-05-12 08:34:04 -05:00
|
|
|
spiTransferTx = (pfnSpiTransfer)spiTransferX;
|
|
|
|
spiTransferRx = (pfnSpiTransfer)spiTransferX;
|
|
|
|
spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
|
|
|
|
spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-02-06 06:31:31 -06:00
|
|
|
_SS_WRITE(HIGH);
|
2017-07-18 18:29:06 -05:00
|
|
|
WRITE(MOSI_PIN, HIGH);
|
|
|
|
WRITE(SCK_PIN, LOW);
|
|
|
|
}
|
|
|
|
|
2018-01-03 05:12:25 -06:00
|
|
|
/** Begin SPI transaction, set clock, bit order, data mode */
|
|
|
|
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
|
|
|
|
// TODO: to be implemented
|
2018-01-05 10:10:55 -06:00
|
|
|
}
|
|
|
|
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
#pragma GCC reset_options
|
|
|
|
|
2018-05-12 08:34:04 -05:00
|
|
|
#else // !SOFTWARE_SPI
|
2018-03-10 22:46:32 -06:00
|
|
|
|
2019-02-06 06:31:31 -06:00
|
|
|
#define WHILE_TX(N) while ((SPI0->SPI_SR & SPI_SR_TDRE) == (N))
|
|
|
|
#define WHILE_RX(N) while ((SPI0->SPI_SR & SPI_SR_RDRF) == (N))
|
|
|
|
#define FLUSH_TX() do{ WHILE_RX(1) SPI0->SPI_RDR; }while(0)
|
|
|
|
|
2018-03-11 10:28:46 -05:00
|
|
|
#if MB(ALLIGATOR)
|
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
// slave selects controlled by SPI controller
|
|
|
|
// doesn't support changing SPI speeds for SD card
|
2018-03-11 10:28:46 -05:00
|
|
|
|
2019-07-09 22:30:06 -05:00
|
|
|
// ------------------------
|
2018-03-10 22:46:32 -06:00
|
|
|
// hardware SPI
|
2019-07-09 22:30:06 -05:00
|
|
|
// ------------------------
|
2018-10-17 10:33:31 -05:00
|
|
|
static bool spiInitialized = false;
|
|
|
|
|
|
|
|
void spiInit(uint8_t spiRate) {
|
|
|
|
if (spiInitialized) return;
|
|
|
|
|
|
|
|
// 8.4 MHz, 4 MHz, 2 MHz, 1 MHz, 0.5 MHz, 0.329 MHz, 0.329 MHz
|
|
|
|
constexpr int spiDivider[] = { 10, 21, 42, 84, 168, 255, 255 };
|
|
|
|
if (spiRate > 6) spiRate = 1;
|
|
|
|
|
|
|
|
// Set SPI mode 1, clock, select not active after transfer, with delay between transfers
|
|
|
|
SPI_ConfigureNPCS(SPI0, SPI_CHAN_DAC,
|
|
|
|
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDivider[spiRate]) |
|
|
|
|
SPI_CSR_DLYBCT(1));
|
|
|
|
// Set SPI mode 0, clock, select not active after transfer, with delay between transfers
|
|
|
|
SPI_ConfigureNPCS(SPI0, SPI_CHAN_EEPROM1, SPI_CSR_NCPHA |
|
|
|
|
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDivider[spiRate]) |
|
|
|
|
SPI_CSR_DLYBCT(1));
|
|
|
|
|
|
|
|
// Set SPI mode 0, clock, select not active after transfer, with delay between transfers
|
|
|
|
SPI_ConfigureNPCS(SPI0, SPI_CHAN, SPI_CSR_NCPHA |
|
|
|
|
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDivider[spiRate]) |
|
|
|
|
SPI_CSR_DLYBCT(1));
|
|
|
|
SPI_Enable(SPI0);
|
|
|
|
spiInitialized = true;
|
|
|
|
}
|
2018-03-10 22:46:32 -06:00
|
|
|
|
|
|
|
void spiBegin() {
|
2018-10-17 10:33:31 -05:00
|
|
|
if (spiInitialized) return;
|
|
|
|
|
|
|
|
// Configure SPI pins
|
|
|
|
PIO_Configure(
|
|
|
|
g_APinDescription[SCK_PIN].pPort,
|
|
|
|
g_APinDescription[SCK_PIN].ulPinType,
|
|
|
|
g_APinDescription[SCK_PIN].ulPin,
|
|
|
|
g_APinDescription[SCK_PIN].ulPinConfiguration);
|
|
|
|
PIO_Configure(
|
|
|
|
g_APinDescription[MOSI_PIN].pPort,
|
|
|
|
g_APinDescription[MOSI_PIN].ulPinType,
|
|
|
|
g_APinDescription[MOSI_PIN].ulPin,
|
|
|
|
g_APinDescription[MOSI_PIN].ulPinConfiguration);
|
|
|
|
PIO_Configure(
|
|
|
|
g_APinDescription[MISO_PIN].pPort,
|
|
|
|
g_APinDescription[MISO_PIN].ulPinType,
|
|
|
|
g_APinDescription[MISO_PIN].ulPin,
|
|
|
|
g_APinDescription[MISO_PIN].ulPinConfiguration);
|
|
|
|
|
|
|
|
// set master mode, peripheral select, fault detection
|
|
|
|
SPI_Configure(SPI0, ID_SPI0, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS);
|
|
|
|
SPI_Enable(SPI0);
|
|
|
|
|
|
|
|
SET_OUTPUT(DAC0_SYNC);
|
|
|
|
#if EXTRUDERS > 1
|
|
|
|
SET_OUTPUT(DAC1_SYNC);
|
|
|
|
WRITE(DAC1_SYNC, HIGH);
|
|
|
|
#endif
|
|
|
|
SET_OUTPUT(SPI_EEPROM1_CS);
|
|
|
|
SET_OUTPUT(SPI_EEPROM2_CS);
|
|
|
|
SET_OUTPUT(SPI_FLASH_CS);
|
|
|
|
WRITE(DAC0_SYNC, HIGH);
|
2019-01-19 20:27:39 -06:00
|
|
|
WRITE(SPI_EEPROM1_CS, HIGH);
|
|
|
|
WRITE(SPI_EEPROM2_CS, HIGH);
|
|
|
|
WRITE(SPI_FLASH_CS, HIGH);
|
|
|
|
WRITE(SS_PIN, HIGH);
|
2018-10-17 10:33:31 -05:00
|
|
|
|
2019-02-06 06:31:31 -06:00
|
|
|
OUT_WRITE(SDSS, LOW);
|
2018-10-17 10:33:31 -05:00
|
|
|
|
|
|
|
PIO_Configure(
|
|
|
|
g_APinDescription[SPI_PIN].pPort,
|
|
|
|
g_APinDescription[SPI_PIN].ulPinType,
|
|
|
|
g_APinDescription[SPI_PIN].ulPin,
|
2019-02-06 06:31:31 -06:00
|
|
|
g_APinDescription[SPI_PIN].ulPinConfiguration
|
|
|
|
);
|
2018-10-17 10:33:31 -05:00
|
|
|
|
|
|
|
spiInit(1);
|
2017-07-18 18:29:06 -05:00
|
|
|
}
|
|
|
|
|
2018-10-17 10:33:31 -05:00
|
|
|
// Read single byte from SPI
|
|
|
|
uint8_t spiRec() {
|
|
|
|
// write dummy byte with address and end transmission flag
|
|
|
|
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN) | SPI_TDR_LASTXFER;
|
|
|
|
|
2019-02-06 06:31:31 -06:00
|
|
|
WHILE_TX(0);
|
|
|
|
WHILE_RX(0);
|
|
|
|
|
2018-10-17 10:33:31 -05:00
|
|
|
//DELAY_US(1U);
|
|
|
|
return SPI0->SPI_RDR;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t spiRec(uint32_t chan) {
|
2019-02-06 06:31:31 -06:00
|
|
|
|
|
|
|
WHILE_TX(0);
|
|
|
|
FLUSH_RX();
|
2018-10-17 10:33:31 -05:00
|
|
|
|
|
|
|
// write dummy byte with address and end transmission flag
|
|
|
|
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(chan) | SPI_TDR_LASTXFER;
|
2019-02-06 06:31:31 -06:00
|
|
|
WHILE_RX(0);
|
2018-10-17 10:33:31 -05:00
|
|
|
|
|
|
|
return SPI0->SPI_RDR;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read from SPI into buffer
|
|
|
|
void spiRead(uint8_t* buf, uint16_t nbyte) {
|
2019-02-20 04:00:49 -06:00
|
|
|
if (!nbyte) return;
|
|
|
|
--nbyte;
|
2018-10-17 10:33:31 -05:00
|
|
|
for (int i = 0; i < nbyte; i++) {
|
2019-02-06 06:31:31 -06:00
|
|
|
//WHILE_TX(0);
|
2018-10-17 10:33:31 -05:00
|
|
|
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN);
|
2019-02-06 06:31:31 -06:00
|
|
|
WHILE_RX(0);
|
2018-10-17 10:33:31 -05:00
|
|
|
buf[i] = SPI0->SPI_RDR;
|
|
|
|
//DELAY_US(1U);
|
2018-03-10 22:46:32 -06:00
|
|
|
}
|
2018-10-17 10:33:31 -05:00
|
|
|
buf[nbyte] = spiRec();
|
2017-07-18 18:29:06 -05:00
|
|
|
}
|
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
// Write single byte to SPI
|
2019-02-20 04:00:49 -06:00
|
|
|
void spiSend(const byte b) {
|
2018-03-10 22:46:32 -06:00
|
|
|
// write byte with address and end transmission flag
|
|
|
|
SPI0->SPI_TDR = (uint32_t)b | SPI_PCS(SPI_CHAN) | SPI_TDR_LASTXFER;
|
2019-02-06 06:31:31 -06:00
|
|
|
WHILE_TX(0);
|
|
|
|
WHILE_RX(0);
|
2017-07-18 18:29:06 -05:00
|
|
|
SPI0->SPI_RDR;
|
2018-05-12 08:34:04 -05:00
|
|
|
//DELAY_US(1U);
|
2017-07-18 18:29:06 -05:00
|
|
|
}
|
|
|
|
|
2019-02-20 04:00:49 -06:00
|
|
|
void spiSend(const uint8_t* buf, size_t nbyte) {
|
|
|
|
if (!nbyte) return;
|
|
|
|
--nbyte;
|
|
|
|
for (size_t i = 0; i < nbyte; i++) {
|
2018-03-10 22:46:32 -06:00
|
|
|
SPI0->SPI_TDR = (uint32_t)buf[i] | SPI_PCS(SPI_CHAN);
|
2019-02-06 06:31:31 -06:00
|
|
|
WHILE_TX(0);
|
|
|
|
WHILE_RX(0);
|
2018-03-10 22:46:32 -06:00
|
|
|
SPI0->SPI_RDR;
|
2018-05-12 08:34:04 -05:00
|
|
|
//DELAY_US(1U);
|
2018-03-10 22:46:32 -06:00
|
|
|
}
|
2019-02-20 04:00:49 -06:00
|
|
|
spiSend(buf[nbyte]);
|
2018-03-10 22:46:32 -06:00
|
|
|
}
|
2017-07-18 18:29:06 -05:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
void spiSend(uint32_t chan, byte b) {
|
2019-02-06 06:31:31 -06:00
|
|
|
WHILE_TX(0);
|
2018-03-10 22:46:32 -06:00
|
|
|
// write byte with address and end transmission flag
|
|
|
|
SPI0->SPI_TDR = (uint32_t)b | SPI_PCS(chan) | SPI_TDR_LASTXFER;
|
2019-02-06 06:31:31 -06:00
|
|
|
WHILE_RX(0);
|
|
|
|
FLUSH_RX();
|
2017-07-18 18:29:06 -05:00
|
|
|
}
|
|
|
|
|
2019-02-20 04:00:49 -06:00
|
|
|
void spiSend(uint32_t chan, const uint8_t* buf, size_t nbyte) {
|
|
|
|
if (!nbyte) return;
|
|
|
|
--nbyte;
|
|
|
|
for (size_t i = 0; i < nbyte; i++) {
|
2019-02-06 06:31:31 -06:00
|
|
|
WHILE_TX(0);
|
2018-03-10 22:46:32 -06:00
|
|
|
SPI0->SPI_TDR = (uint32_t)buf[i] | SPI_PCS(chan);
|
2019-02-06 06:31:31 -06:00
|
|
|
WHILE_RX(0);
|
|
|
|
FLUSH_RX();
|
2018-03-10 22:46:32 -06:00
|
|
|
}
|
2019-02-20 04:00:49 -06:00
|
|
|
spiSend(chan, buf[nbyte]);
|
2018-03-10 22:46:32 -06:00
|
|
|
}
|
2018-03-05 10:51:09 -06:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
// Write from buffer to SPI
|
|
|
|
void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
|
|
|
SPI0->SPI_TDR = (uint32_t)token | SPI_PCS(SPI_CHAN);
|
2019-02-06 06:31:31 -06:00
|
|
|
WHILE_TX(0);
|
|
|
|
//WHILE_RX(0);
|
2018-03-10 22:46:32 -06:00
|
|
|
//SPI0->SPI_RDR;
|
|
|
|
for (int i = 0; i < 511; i++) {
|
|
|
|
SPI0->SPI_TDR = (uint32_t)buf[i] | SPI_PCS(SPI_CHAN);
|
2019-02-06 06:31:31 -06:00
|
|
|
WHILE_TX(0);
|
|
|
|
WHILE_RX(0);
|
2018-03-10 22:46:32 -06:00
|
|
|
SPI0->SPI_RDR;
|
2018-05-12 08:34:04 -05:00
|
|
|
//DELAY_US(1U);
|
2018-03-10 22:46:32 -06:00
|
|
|
}
|
|
|
|
spiSend(buf[511]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Begin SPI transaction, set clock, bit order, data mode */
|
|
|
|
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
|
|
|
|
// TODO: to be implemented
|
|
|
|
}
|
|
|
|
|
2018-10-17 10:33:31 -05:00
|
|
|
#else // U8G compatible hardware SPI
|
2018-03-11 10:28:46 -05:00
|
|
|
|
2018-03-23 09:37:58 -05:00
|
|
|
#define SPI_MODE_0_DUE_HW 2 // DUE CPHA control bit is inverted
|
|
|
|
#define SPI_MODE_1_DUE_HW 3
|
|
|
|
#define SPI_MODE_2_DUE_HW 0
|
|
|
|
#define SPI_MODE_3_DUE_HW 1
|
|
|
|
|
2019-04-21 20:48:53 -05:00
|
|
|
/**
|
|
|
|
* The DUE SPI controller is set up so the upper word of the longword
|
|
|
|
* written to the transmit data register selects which SPI Chip Select
|
|
|
|
* Register is used. This allows different streams to have different SPI
|
|
|
|
* settings.
|
|
|
|
*
|
|
|
|
* In practice it's spooky. Some combinations hang the system, while others
|
|
|
|
* upset the peripheral device.
|
|
|
|
*
|
|
|
|
* SPI mode should be the same for all streams. The FYSETC_MINI_12864 gets
|
|
|
|
* upset if the clock phase changes after chip select goes active.
|
|
|
|
*
|
|
|
|
* SPI_CSR_CSAAT should be set for all streams. If not the WHILE_TX(0)
|
|
|
|
* macro returns immediately which can result in the SPI chip select going
|
|
|
|
* inactive before all the data has been sent.
|
|
|
|
*
|
|
|
|
* The TMC2130 library uses SPI0->SPI_CSR[3].
|
|
|
|
*
|
|
|
|
* The U8G hardware SPI uses SPI0->SPI_CSR[0]. The system hangs and/or the
|
|
|
|
* FYSETC_MINI_12864 gets upset if lower baud rates are used and the SD card
|
|
|
|
* is inserted or removed.
|
|
|
|
*
|
|
|
|
* The SD card uses SPI0->SPI_CSR[3]. Efforts were made to use [1] and [2]
|
|
|
|
* but they all resulted in hangs or garbage on the LCD.
|
|
|
|
*
|
|
|
|
* The SPI controlled chip selects are NOT enabled in the GPIO controller.
|
|
|
|
* The application must control the chip select.
|
|
|
|
*
|
|
|
|
* All of the above can be avoided by defining FORCE_SOFT_SPI to force the
|
|
|
|
* display to use software SPI.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2018-04-04 20:13:27 -05:00
|
|
|
void spiInit(uint8_t spiRate=6) { // Default to slowest rate if not specified)
|
2019-04-21 20:48:53 -05:00
|
|
|
// Also sets U8G SPI rate to 4MHz and the SPI mode to 3
|
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
// 8.4 MHz, 4 MHz, 2 MHz, 1 MHz, 0.5 MHz, 0.329 MHz, 0.329 MHz
|
2018-10-17 10:33:31 -05:00
|
|
|
constexpr int spiDivider[] = { 10, 21, 42, 84, 168, 255, 255 };
|
2018-04-04 20:13:27 -05:00
|
|
|
if (spiRate > 6) spiRate = 1;
|
2018-03-10 22:46:32 -06:00
|
|
|
|
2018-04-04 20:13:27 -05:00
|
|
|
// Enable PIOA and SPI0
|
2018-03-10 22:46:32 -06:00
|
|
|
REG_PMC_PCER0 = (1UL << ID_PIOA) | (1UL << ID_SPI0);
|
|
|
|
|
2018-04-04 20:13:27 -05:00
|
|
|
// Disable PIO on A26 and A27
|
2018-05-08 09:17:44 -05:00
|
|
|
REG_PIOA_PDR = 0x0C000000;
|
2019-02-06 06:31:31 -06:00
|
|
|
OUT_WRITE(SDSS, HIGH);
|
2018-03-10 22:46:32 -06:00
|
|
|
|
2018-04-04 20:13:27 -05:00
|
|
|
// Reset SPI0 (from sam lib)
|
2018-03-10 22:46:32 -06:00
|
|
|
SPI0->SPI_CR = SPI_CR_SPIDIS;
|
|
|
|
SPI0->SPI_CR = SPI_CR_SWRST;
|
|
|
|
SPI0->SPI_CR = SPI_CR_SWRST;
|
|
|
|
SPI0->SPI_CR = SPI_CR_SPIEN;
|
|
|
|
|
2018-04-04 20:13:27 -05:00
|
|
|
// TMC2103 compatible setup
|
|
|
|
// Master mode, no fault detection, PCS bits in data written to TDR select CSR register
|
|
|
|
SPI0->SPI_MR = SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS;
|
2019-04-21 20:48:53 -05:00
|
|
|
// SPI mode 3, 8 Bit data transfer, baud rate
|
|
|
|
SPI0->SPI_CSR[3] = SPI_CSR_SCBR(spiDivider[spiRate]) | SPI_CSR_CSAAT | SPI_MODE_3_DUE_HW; // use same CSR as TMC2130
|
|
|
|
SPI0->SPI_CSR[0] = SPI_CSR_SCBR(spiDivider[1]) | SPI_CSR_CSAAT | SPI_MODE_3_DUE_HW; // U8G default to 4MHz
|
2018-10-17 10:33:31 -05:00
|
|
|
}
|
|
|
|
|
2019-02-06 06:31:31 -06:00
|
|
|
void spiBegin() { spiInit(); }
|
2018-03-10 22:46:32 -06:00
|
|
|
|
|
|
|
static uint8_t spiTransfer(uint8_t data) {
|
2019-02-06 06:31:31 -06:00
|
|
|
WHILE_TX(0);
|
2019-04-21 20:48:53 -05:00
|
|
|
SPI0->SPI_TDR = (uint32_t)data | 0x00070000UL; // Add TMC2130 PCS bits to every byte (use SPI0->SPI_CSR[3])
|
2019-02-06 06:31:31 -06:00
|
|
|
WHILE_TX(0);
|
|
|
|
WHILE_RX(0);
|
2018-03-10 22:46:32 -06:00
|
|
|
return SPI0->SPI_RDR;
|
|
|
|
}
|
|
|
|
|
2019-02-06 06:31:31 -06:00
|
|
|
uint8_t spiRec() { return (uint8_t)spiTransfer(0xFF); }
|
2018-03-10 22:46:32 -06:00
|
|
|
|
2018-04-04 20:13:27 -05:00
|
|
|
void spiRead(uint8_t* buf, uint16_t nbyte) {
|
2019-02-20 04:00:49 -06:00
|
|
|
for (int i = 0; i < nbyte; i++)
|
|
|
|
buf[i] = spiTransfer(0xFF);
|
2018-03-10 22:46:32 -06:00
|
|
|
}
|
|
|
|
|
2019-02-06 06:31:31 -06:00
|
|
|
void spiSend(uint8_t data) { spiTransfer(data); }
|
2018-03-10 22:46:32 -06:00
|
|
|
|
2019-02-06 06:31:31 -06:00
|
|
|
void spiSend(const uint8_t* buf, size_t nbyte) {
|
2019-02-20 04:00:49 -06:00
|
|
|
for (uint16_t i = 0; i < nbyte; i++)
|
|
|
|
spiTransfer(buf[i]);
|
2018-03-10 22:46:32 -06:00
|
|
|
}
|
2018-01-05 10:10:55 -06:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
|
|
|
spiTransfer(token);
|
|
|
|
for (uint16_t i = 0; i < 512; i++)
|
|
|
|
spiTransfer(buf[i]);
|
2018-03-11 10:28:46 -05:00
|
|
|
}
|
|
|
|
|
2018-05-12 08:34:04 -05:00
|
|
|
#endif // !ALLIGATOR
|
|
|
|
#endif // !SOFTWARE_SPI
|
2017-07-18 18:29:06 -05:00
|
|
|
|
|
|
|
#endif // ARDUINO_ARCH_SAM
|