Standardize Marlin SPI (part 1) (#19989)
This commit is contained in:
parent
97d7af7a23
commit
85d094bbb4
1
.github/workflows/test-builds.yml
vendored
1
.github/workflows/test-builds.yml
vendored
@ -83,6 +83,7 @@ jobs:
|
|||||||
- STM32F103RET6_creality
|
- STM32F103RET6_creality
|
||||||
- LERDGEX
|
- LERDGEX
|
||||||
- mks_robin_nano35
|
- mks_robin_nano35
|
||||||
|
- mks_robin_nano35_stm32
|
||||||
- NUCLEO_F767ZI
|
- NUCLEO_F767ZI
|
||||||
|
|
||||||
# Put lengthy tests last
|
# Put lengthy tests last
|
||||||
|
@ -127,11 +127,9 @@
|
|||||||
for (uint16_t i = 0; i < nbyte; i++) doio(buf[i]);
|
for (uint16_t i = 0; i < nbyte; i++) doio(buf[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void spiSend(uint32_t chan, byte b) {
|
void spiSend(uint32_t chan, byte b) {}
|
||||||
}
|
|
||||||
|
|
||||||
void spiSend(uint32_t chan, const uint8_t* buf, size_t nbyte) {
|
void spiSend(uint32_t chan, const uint8_t* buf, size_t nbyte) {}
|
||||||
}
|
|
||||||
|
|
||||||
// Read single byte from SPI
|
// Read single byte from SPI
|
||||||
uint8_t spiRec() { return doio(0xFF); }
|
uint8_t spiRec() { return doio(0xFF); }
|
||||||
@ -143,9 +141,7 @@
|
|||||||
for (uint16_t i = 0; i < nbyte; i++) buf[i] = doio(0xFF);
|
for (uint16_t i = 0; i < nbyte; i++) buf[i] = doio(0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t spiTransfer(uint8_t b) {
|
uint8_t spiTransfer(uint8_t b) { return doio(b); }
|
||||||
return doio(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write from buffer to SPI
|
// Write from buffer to SPI
|
||||||
void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
||||||
@ -201,6 +197,15 @@ SPIClass::SPIClass(uint8_t device) {
|
|||||||
GPDMA_Init();
|
GPDMA_Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPIClass::SPIClass(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel) {
|
||||||
|
#if BOARD_NR_SPI >= 1
|
||||||
|
if (mosi == BOARD_SPI1_MOSI_PIN) SPIClass(1);
|
||||||
|
#endif
|
||||||
|
#if BOARD_NR_SPI >= 2
|
||||||
|
if (mosi == BOARD_SPI2_MOSI_PIN) SPIClass(2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void SPIClass::begin() {
|
void SPIClass::begin() {
|
||||||
// Init the SPI pins in the first begin call
|
// Init the SPI pins in the first begin call
|
||||||
if ((_currentSetting->spi_d == LPC_SSP0 && spiInitialised[0] == false) ||
|
if ((_currentSetting->spi_d == LPC_SSP0 && spiInitialised[0] == false) ||
|
||||||
@ -331,25 +336,15 @@ void SPIClass::read(uint8_t *buf, uint32_t len) {
|
|||||||
for (uint16_t i = 0; i < len; i++) buf[i] = transfer(0xFF);
|
for (uint16_t i = 0; i < len; i++) buf[i] = transfer(0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPIClass::setClock(uint32_t clock) {
|
void SPIClass::setClock(uint32_t clock) { _currentSetting->clock = clock; }
|
||||||
_currentSetting->clock = clock;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPIClass::setModule(uint8_t device) {
|
void SPIClass::setModule(uint8_t device) { _currentSetting = &_settings[device - 1]; } // SPI channels are called 1, 2, and 3 but the array is zero-indexed
|
||||||
_currentSetting = &_settings[device - 1];// SPI channels are called 1 2 and 3 but the array is zero indexed
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPIClass::setBitOrder(uint8_t bitOrder) {
|
void SPIClass::setBitOrder(uint8_t bitOrder) { _currentSetting->bitOrder = bitOrder; }
|
||||||
_currentSetting->bitOrder = bitOrder;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPIClass::setDataMode(uint8_t dataMode) {
|
void SPIClass::setDataMode(uint8_t dataMode) { _currentSetting->dataMode = dataMode; }
|
||||||
_currentSetting->dataMode = dataMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPIClass::setDataSize(uint32_t ds) {
|
void SPIClass::setDataSize(uint32_t dataSize) { _currentSetting->dataSize = dataSize; }
|
||||||
_currentSetting->dataSize = ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up/tear down
|
* Set up/tear down
|
||||||
|
45
Marlin/src/HAL/LPC1768/MarlinSPI.h
Normal file
45
Marlin/src/HAL/LPC1768/MarlinSPI.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Marlin 3D Printer Firmware
|
||||||
|
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||||
|
*
|
||||||
|
* Based on Sprinter and grbl.
|
||||||
|
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marlin currently requires 3 SPI classes:
|
||||||
|
*
|
||||||
|
* SPIClass:
|
||||||
|
* This class is normally provided by frameworks and has a semi-default interface.
|
||||||
|
* This is needed because some libraries reference it globally.
|
||||||
|
*
|
||||||
|
* SPISettings:
|
||||||
|
* Container for SPI configs for SPIClass. As above, libraries may reference it globally.
|
||||||
|
*
|
||||||
|
* These two classes are often provided by frameworks so we cannot extend them to add
|
||||||
|
* useful methods for Marlin.
|
||||||
|
*
|
||||||
|
* MarlinSPI:
|
||||||
|
* Provides the default SPIClass interface plus some Marlin goodies such as a simplified
|
||||||
|
* interface for SPI DMA transfer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using MarlinSPI = SPIClass;
|
@ -126,6 +126,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
SPIClass(uint8_t spiPortNumber);
|
SPIClass(uint8_t spiPortNumber);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init using pins
|
||||||
|
*/
|
||||||
|
SPIClass(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel = (pin_t)-1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select and configure the current selected SPI device to use
|
* Select and configure the current selected SPI device to use
|
||||||
*/
|
*/
|
||||||
|
161
Marlin/src/HAL/STM32/MarlinSPI.cpp
Normal file
161
Marlin/src/HAL/STM32/MarlinSPI.cpp
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/**
|
||||||
|
* Marlin 3D Printer Firmware
|
||||||
|
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||||
|
*
|
||||||
|
* Based on Sprinter and grbl.
|
||||||
|
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MarlinSPI.h"
|
||||||
|
|
||||||
|
static void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb, uint32_t dataSize) {
|
||||||
|
spi_init(obj, speed, mode, msb);
|
||||||
|
// spi_init set 8bit always
|
||||||
|
// TODO: copy the code from spi_init and handle data size, to avoid double init always!!
|
||||||
|
if (dataSize != SPI_DATASIZE_8BIT) {
|
||||||
|
obj->handle.Init.DataSize = dataSize;
|
||||||
|
HAL_SPI_Init(&obj->handle);
|
||||||
|
__HAL_SPI_ENABLE(&obj->handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarlinSPI::setClockDivider(uint8_t _div) {
|
||||||
|
_speed = spi_getClkFreq(&_spi);// / _div;
|
||||||
|
_clockDivider = _div;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarlinSPI::begin(void) {
|
||||||
|
//TODO: only call spi_init if any parameter changed!!
|
||||||
|
spi_init(&_spi, _speed, _dataMode, _bitOrder, _dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarlinSPI::setupDma(SPI_HandleTypeDef &_spiHandle, DMA_HandleTypeDef &_dmaHandle, uint32_t direction, bool minc) {
|
||||||
|
_dmaHandle.Init.Direction = direction;
|
||||||
|
_dmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||||
|
_dmaHandle.Init.Mode = DMA_NORMAL;
|
||||||
|
_dmaHandle.Init.Priority = DMA_PRIORITY_LOW;
|
||||||
|
_dmaHandle.Init.MemInc = minc ? DMA_MINC_ENABLE : DMA_MINC_DISABLE;
|
||||||
|
|
||||||
|
if (_dataSize == DATA_SIZE_8BIT) {
|
||||||
|
_dmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||||
|
_dmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_dmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
|
||||||
|
_dmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
|
||||||
|
}
|
||||||
|
#ifdef STM32F4xx
|
||||||
|
_dmaHandle.Init.Channel = DMA_CHANNEL_3;
|
||||||
|
_dmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// start DMA hardware
|
||||||
|
// TODO: check if hardware is already enabled
|
||||||
|
#ifdef SPI1_BASE
|
||||||
|
if (_spiHandle.Instance == SPI1) {
|
||||||
|
#ifdef STM32F1xx
|
||||||
|
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||||
|
_dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Channel3 : DMA1_Channel2;
|
||||||
|
#elif defined(STM32F4xx)
|
||||||
|
__HAL_RCC_DMA2_CLK_ENABLE();
|
||||||
|
_dmaHandle.Instance = DMA2_Stream3;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef SPI2_BASE
|
||||||
|
if (_spiHandle.Instance == SPI2) {
|
||||||
|
#ifdef STM32F1xx
|
||||||
|
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||||
|
_dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Channel5 : DMA1_Channel4;
|
||||||
|
#elif defined(STM32F4xx)
|
||||||
|
//TODO: f4 dma config
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef SPI3_BASE
|
||||||
|
if (_spiHandle.Instance == SPI3) {
|
||||||
|
#ifdef STM32F1xx
|
||||||
|
__HAL_RCC_DMA2_CLK_ENABLE();
|
||||||
|
_dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA2_Channel2 : DMA2_Channel1;
|
||||||
|
#elif defined(STM32F4xx)
|
||||||
|
//TODO: f4 dma config
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HAL_DMA_Init(&_dmaHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte MarlinSPI::transfer(uint8_t _data) {
|
||||||
|
uint8_t rxData = 0xFF;
|
||||||
|
HAL_SPI_TransmitReceive(&_spi.handle, &_data, &rxData, 1, HAL_MAX_DELAY);
|
||||||
|
return rxData;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MarlinSPI::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length) {
|
||||||
|
const uint8_t ff = 0xFF;
|
||||||
|
|
||||||
|
//if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) //only enable if disabled
|
||||||
|
__HAL_SPI_ENABLE(&_spi.handle);
|
||||||
|
|
||||||
|
if (receiveBuf) {
|
||||||
|
setupDma(_spi.handle, _dmaRx, DMA_PERIPH_TO_MEMORY, true);
|
||||||
|
HAL_DMA_Start(&_dmaRx, (uint32_t)&(_spi.handle.Instance->DR), (uint32_t)receiveBuf, length);
|
||||||
|
SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_RXDMAEN); /* Enable Rx DMA Request */
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for 2 lines transfer
|
||||||
|
bool mincTransmit = true;
|
||||||
|
if (transmitBuf == nullptr && _spi.handle.Init.Direction == SPI_DIRECTION_2LINES && _spi.handle.Init.Mode == SPI_MODE_MASTER) {
|
||||||
|
transmitBuf = &ff;
|
||||||
|
mincTransmit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transmitBuf) {
|
||||||
|
setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, mincTransmit);
|
||||||
|
HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
|
||||||
|
SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_TXDMAEN); /* Enable Tx DMA Request */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transmitBuf) {
|
||||||
|
HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
|
||||||
|
HAL_DMA_Abort(&_dmaTx);
|
||||||
|
HAL_DMA_DeInit(&_dmaTx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// while ((_spi.handle.Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE) {}
|
||||||
|
|
||||||
|
if (receiveBuf) {
|
||||||
|
HAL_DMA_PollForTransfer(&_dmaRx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
|
||||||
|
HAL_DMA_Abort(&_dmaRx);
|
||||||
|
HAL_DMA_DeInit(&_dmaRx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MarlinSPI::dmaSend(const void * transmitBuf, uint16_t length, bool minc) {
|
||||||
|
setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, minc);
|
||||||
|
HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
|
||||||
|
__HAL_SPI_ENABLE(&_spi.handle);
|
||||||
|
SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_TXDMAEN); /* Enable Tx DMA Request */
|
||||||
|
HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
|
||||||
|
HAL_DMA_Abort(&_dmaTx);
|
||||||
|
// DeInit objects
|
||||||
|
HAL_DMA_DeInit(&_dmaTx);
|
||||||
|
return 1;
|
||||||
|
}
|
107
Marlin/src/HAL/STM32/MarlinSPI.h
Normal file
107
Marlin/src/HAL/STM32/MarlinSPI.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/**
|
||||||
|
* Marlin 3D Printer Firmware
|
||||||
|
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||||
|
*
|
||||||
|
* Based on Sprinter and grbl.
|
||||||
|
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "HAL.h"
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <utility/spi_com.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marlin currently requires 3 SPI classes:
|
||||||
|
*
|
||||||
|
* SPIClass:
|
||||||
|
* This class is normally provided by frameworks and has a semi-default interface.
|
||||||
|
* This is needed because some libraries reference it globally.
|
||||||
|
*
|
||||||
|
* SPISettings:
|
||||||
|
* Container for SPI configs for SPIClass. As above, libraries may reference it globally.
|
||||||
|
*
|
||||||
|
* These two classes are often provided by frameworks so we cannot extend them to add
|
||||||
|
* useful methods for Marlin.
|
||||||
|
*
|
||||||
|
* MarlinSPI:
|
||||||
|
* Provides the default SPIClass interface plus some Marlin goodies such as a simplified
|
||||||
|
* interface for SPI DMA transfer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DATA_SIZE_8BIT SPI_DATASIZE_8BIT
|
||||||
|
#define DATA_SIZE_16BIT SPI_DATASIZE_16BIT
|
||||||
|
|
||||||
|
class MarlinSPI {
|
||||||
|
public:
|
||||||
|
MarlinSPI() : MarlinSPI(NC, NC, NC, NC) {}
|
||||||
|
|
||||||
|
MarlinSPI(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel = (pin_t)NC) : _mosiPin(mosi), _misoPin(miso), _sckPin(sclk), _ssPin(ssel) {
|
||||||
|
_spi.pin_miso = digitalPinToPinName(_misoPin);
|
||||||
|
_spi.pin_mosi = digitalPinToPinName(_mosiPin);
|
||||||
|
_spi.pin_sclk = digitalPinToPinName(_sckPin);
|
||||||
|
_spi.pin_ssel = digitalPinToPinName(_ssPin);
|
||||||
|
_dataSize = DATA_SIZE_8BIT;
|
||||||
|
_bitOrder = MSBFIRST;
|
||||||
|
_dataMode = SPI_MODE_0;
|
||||||
|
_spi.handle.State = HAL_SPI_STATE_RESET;
|
||||||
|
setClockDivider(SPI_SPEED_CLOCK_DIV2_MHZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
void begin(void);
|
||||||
|
void end(void) {}
|
||||||
|
|
||||||
|
byte transfer(uint8_t _data);
|
||||||
|
uint8_t dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length);
|
||||||
|
uint8_t dmaSend(const void * transmitBuf, uint16_t length, bool minc = true);
|
||||||
|
|
||||||
|
/* These methods are deprecated and kept for compatibility.
|
||||||
|
* Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
|
||||||
|
*/
|
||||||
|
void setBitOrder(BitOrder _order) { _bitOrder = _order; }
|
||||||
|
|
||||||
|
void setDataMode(uint8_t _mode) {
|
||||||
|
switch (_mode) {
|
||||||
|
case SPI_MODE0: _dataMode = SPI_MODE_0; break;
|
||||||
|
case SPI_MODE1: _dataMode = SPI_MODE_1; break;
|
||||||
|
case SPI_MODE2: _dataMode = SPI_MODE_2; break;
|
||||||
|
case SPI_MODE3: _dataMode = SPI_MODE_3; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setClockDivider(uint8_t _div);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupDma(SPI_HandleTypeDef &_spiHandle, DMA_HandleTypeDef &_dmaHandle, uint32_t direction, bool minc = false);
|
||||||
|
|
||||||
|
spi_t _spi;
|
||||||
|
DMA_HandleTypeDef _dmaTx;
|
||||||
|
DMA_HandleTypeDef _dmaRx;
|
||||||
|
BitOrder _bitOrder;
|
||||||
|
spi_mode_e _dataMode;
|
||||||
|
uint8_t _clockDivider;
|
||||||
|
uint32_t _speed;
|
||||||
|
uint32_t _dataSize;
|
||||||
|
pin_t _mosiPin;
|
||||||
|
pin_t _misoPin;
|
||||||
|
pin_t _sckPin;
|
||||||
|
pin_t _ssPin;
|
||||||
|
};
|
@ -105,7 +105,7 @@ void SetTimerInterruptPriorities();
|
|||||||
|
|
||||||
// FORCE_INLINE because these are used in performance-critical situations
|
// FORCE_INLINE because these are used in performance-critical situations
|
||||||
FORCE_INLINE bool HAL_timer_initialized(const uint8_t timer_num) {
|
FORCE_INLINE bool HAL_timer_initialized(const uint8_t timer_num) {
|
||||||
return timer_instance[timer_num] != NULL;
|
return timer_instance[timer_num] != nullptr;
|
||||||
}
|
}
|
||||||
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
|
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
|
||||||
return HAL_timer_initialized(timer_num) ? timer_instance[timer_num]->getCount() : 0;
|
return HAL_timer_initialized(timer_num) ? timer_instance[timer_num]->getCount() : 0;
|
||||||
|
45
Marlin/src/HAL/STM32F1/MarlinSPI.h
Normal file
45
Marlin/src/HAL/STM32F1/MarlinSPI.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Marlin 3D Printer Firmware
|
||||||
|
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||||
|
*
|
||||||
|
* Based on Sprinter and grbl.
|
||||||
|
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marlin currently requires 3 SPI classes:
|
||||||
|
*
|
||||||
|
* SPIClass:
|
||||||
|
* This class is normally provided by frameworks and has a semi-default interface.
|
||||||
|
* This is needed because some libraries reference it globally.
|
||||||
|
*
|
||||||
|
* SPISettings:
|
||||||
|
* Container for SPI configs for SPIClass. As above, libraries may reference it globally.
|
||||||
|
*
|
||||||
|
* These two classes are often provided by frameworks so we cannot extend them to add
|
||||||
|
* useful methods for Marlin.
|
||||||
|
*
|
||||||
|
* MarlinSPI:
|
||||||
|
* Provides the default SPIClass interface plus some Marlin goodies such as a simplified
|
||||||
|
* interface for SPI DMA transfer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using MarlinSPI = SPIClass;
|
@ -147,6 +147,18 @@ SPIClass::SPIClass(uint32_t spi_num) {
|
|||||||
_currentSetting->state = SPI_STATE_IDLE;
|
_currentSetting->state = SPI_STATE_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPIClass::SPIClass(int8_t mosi, int8_t miso, int8_t sclk, int8_t ssel) {
|
||||||
|
#if BOARD_NR_SPI >= 1
|
||||||
|
if (mosi == BOARD_SPI1_MOSI_PIN) SPIClass(1);
|
||||||
|
#endif
|
||||||
|
#if BOARD_NR_SPI >= 2
|
||||||
|
if (mosi == BOARD_SPI2_MOSI_PIN) SPIClass(2);
|
||||||
|
#endif
|
||||||
|
#if BOARD_NR_SPI >= 3
|
||||||
|
if (mosi == BOARD_SPI3_MOSI_PIN) SPIClass(3);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up/tear down
|
* Set up/tear down
|
||||||
*/
|
*/
|
||||||
|
@ -163,6 +163,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
SPIClass(uint32_t spiPortNumber);
|
SPIClass(uint32_t spiPortNumber);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init using pins
|
||||||
|
*/
|
||||||
|
SPIClass(int8_t mosi, int8_t miso, int8_t sclk, int8_t ssel=-1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0).
|
* @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0).
|
||||||
*/
|
*/
|
||||||
|
@ -32,7 +32,12 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* lcd_put_u8str_ind_P
|
* lcd_put_u8str_ind_P
|
||||||
* Print a string with an index substituted within it
|
*
|
||||||
|
* Print a string with an index substituted within it:
|
||||||
|
*
|
||||||
|
* = displays '0'....'10' for indexes 0 - 10
|
||||||
|
* ~ displays '1'....'11' for indexes 0 - 10
|
||||||
|
* * displays 'E1'...'E11' for indexes 0 - 10 (By default. Uses LCD_FIRST_TOOL)
|
||||||
*/
|
*/
|
||||||
lcd_uint_t lcd_put_u8str_ind_P(PGM_P const pstr, const int8_t ind, PGM_P const inStr/*=nullptr*/, const lcd_uint_t maxlen/*=LCD_WIDTH*/) {
|
lcd_uint_t lcd_put_u8str_ind_P(PGM_P const pstr, const int8_t ind, PGM_P const inStr/*=nullptr*/, const lcd_uint_t maxlen/*=LCD_WIDTH*/) {
|
||||||
uint8_t *p = (uint8_t*)pstr;
|
uint8_t *p = (uint8_t*)pstr;
|
||||||
|
@ -72,11 +72,10 @@ void TFT_String::add_glyphs(const uint8_t *font) {
|
|||||||
glyphs[glyph] = (glyph_t *)pointer;
|
glyphs[glyph] = (glyph_t *)pointer;
|
||||||
pointer += sizeof(glyph_t) + ((glyph_t *)pointer)->DataSize;
|
pointer += sizeof(glyph_t) + ((glyph_t *)pointer)->DataSize;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
pointer++;
|
pointer++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void TFT_String::set() {
|
void TFT_String::set() {
|
||||||
*data = 0x00;
|
*data = 0x00;
|
||||||
@ -86,6 +85,13 @@ void TFT_String::set() {
|
|||||||
|
|
||||||
uint8_t read_byte(uint8_t *byte) { return *byte; }
|
uint8_t read_byte(uint8_t *byte) { return *byte; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a string, applying substitutions for the following characters:
|
||||||
|
*
|
||||||
|
* = displays '0'....'10' for indexes 0 - 10
|
||||||
|
* ~ displays '1'....'11' for indexes 0 - 10
|
||||||
|
* * displays 'E1'...'E11' for indexes 0 - 10 (By default. Uses LCD_FIRST_TOOL)
|
||||||
|
*/
|
||||||
void TFT_String::add(uint8_t *string, int8_t index, uint8_t *itemString) {
|
void TFT_String::add(uint8_t *string, int8_t index, uint8_t *itemString) {
|
||||||
wchar_t wchar;
|
wchar_t wchar;
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#if HAS_SPI_FLASH
|
#if HAS_SPI_FLASH
|
||||||
|
|
||||||
#include "W25Qxx.h"
|
#include "W25Qxx.h"
|
||||||
#include <SPI.h>
|
|
||||||
|
|
||||||
W25QXXFlash W25QXX;
|
W25QXXFlash W25QXX;
|
||||||
|
|
||||||
@ -41,6 +40,11 @@ W25QXXFlash W25QXX;
|
|||||||
#ifndef SPI_FLASH_CS_PIN
|
#ifndef SPI_FLASH_CS_PIN
|
||||||
#define SPI_FLASH_CS_PIN W25QXX_CS_PIN
|
#define SPI_FLASH_CS_PIN W25QXX_CS_PIN
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef NC
|
||||||
|
#define NC -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MarlinSPI W25QXXFlash::mySPI(SPI_FLASH_MOSI_PIN, SPI_FLASH_MISO_PIN, SPI_FLASH_SCK_PIN, NC);
|
||||||
|
|
||||||
#define W25QXX_CS_H OUT_WRITE(SPI_FLASH_CS_PIN, HIGH)
|
#define W25QXX_CS_H OUT_WRITE(SPI_FLASH_CS_PIN, HIGH)
|
||||||
#define W25QXX_CS_L OUT_WRITE(SPI_FLASH_CS_PIN, LOW)
|
#define W25QXX_CS_L OUT_WRITE(SPI_FLASH_CS_PIN, LOW)
|
||||||
@ -69,11 +73,11 @@ void W25QXXFlash::init(uint8_t spiRate) {
|
|||||||
case SPI_SPEED_6: clock = SPI_CLOCK_DIV64; break;
|
case SPI_SPEED_6: clock = SPI_CLOCK_DIV64; break;
|
||||||
default: clock = SPI_CLOCK_DIV2;// Default from the SPI library
|
default: clock = SPI_CLOCK_DIV2;// Default from the SPI library
|
||||||
}
|
}
|
||||||
SPI.setModule(SPI_DEVICE);
|
|
||||||
SPI.begin();
|
mySPI.setClockDivider(clock);
|
||||||
SPI.setClockDivider(clock);
|
mySPI.setBitOrder(MSBFIRST);
|
||||||
SPI.setBitOrder(MSBFIRST);
|
mySPI.setDataMode(SPI_MODE0);
|
||||||
SPI.setDataMode(SPI_MODE0);
|
mySPI.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,12 +86,12 @@ void W25QXXFlash::init(uint8_t spiRate) {
|
|||||||
* @return Byte received
|
* @return Byte received
|
||||||
*/
|
*/
|
||||||
uint8_t W25QXXFlash::spi_flash_Rec() {
|
uint8_t W25QXXFlash::spi_flash_Rec() {
|
||||||
const uint8_t returnByte = SPI.transfer(0xFF);
|
const uint8_t returnByte = mySPI.transfer(0xFF);
|
||||||
return returnByte;
|
return returnByte;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t W25QXXFlash::spi_flash_read_write_byte(uint8_t data) {
|
uint8_t W25QXXFlash::spi_flash_read_write_byte(uint8_t data) {
|
||||||
const uint8_t returnByte = SPI.transfer(data);
|
const uint8_t returnByte = mySPI.transfer(data);
|
||||||
return returnByte;
|
return returnByte;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +104,9 @@ uint8_t W25QXXFlash::spi_flash_read_write_byte(uint8_t data) {
|
|||||||
*
|
*
|
||||||
* @details Uses DMA
|
* @details Uses DMA
|
||||||
*/
|
*/
|
||||||
void W25QXXFlash::spi_flash_Read(uint8_t* buf, uint16_t nbyte) { SPI.dmaTransfer(0, const_cast<uint8_t*>(buf), nbyte); }
|
void W25QXXFlash::spi_flash_Read(uint8_t* buf, uint16_t nbyte) {
|
||||||
|
mySPI.dmaTransfer(0, const_cast<uint8_t*>(buf), nbyte);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send a single byte on SPI port
|
* @brief Send a single byte on SPI port
|
||||||
@ -109,7 +115,7 @@ void W25QXXFlash::spi_flash_Read(uint8_t* buf, uint16_t nbyte) { SPI.dmaTransfer
|
|||||||
*
|
*
|
||||||
* @details
|
* @details
|
||||||
*/
|
*/
|
||||||
void W25QXXFlash::spi_flash_Send(uint8_t b) { SPI.send(b); }
|
void W25QXXFlash::spi_flash_Send(uint8_t b) { mySPI.transfer(b); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Write token and then write from 512 byte buffer to SPI (for SD card)
|
* @brief Write token and then write from 512 byte buffer to SPI (for SD card)
|
||||||
@ -120,8 +126,8 @@ void W25QXXFlash::spi_flash_Send(uint8_t b) { SPI.send(b); }
|
|||||||
* @details Use DMA
|
* @details Use DMA
|
||||||
*/
|
*/
|
||||||
void W25QXXFlash::spi_flash_SendBlock(uint8_t token, const uint8_t* buf) {
|
void W25QXXFlash::spi_flash_SendBlock(uint8_t token, const uint8_t* buf) {
|
||||||
SPI.send(token);
|
mySPI.transfer(token);
|
||||||
SPI.dmaSend(const_cast<uint8_t*>(buf), 512);
|
mySPI.dmaSend(const_cast<uint8_t*>(buf), 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t W25QXXFlash::W25QXX_ReadID(void) {
|
uint16_t W25QXXFlash::W25QXX_ReadID(void) {
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include HAL_PATH(../HAL, MarlinSPI.h)
|
||||||
|
|
||||||
#define W25X_WriteEnable 0x06
|
#define W25X_WriteEnable 0x06
|
||||||
#define W25X_WriteDisable 0x04
|
#define W25X_WriteDisable 0x04
|
||||||
#define W25X_ReadStatusReg 0x05
|
#define W25X_ReadStatusReg 0x05
|
||||||
@ -49,6 +51,8 @@
|
|||||||
#define SPI_FLASH_PerWritePageSize 256
|
#define SPI_FLASH_PerWritePageSize 256
|
||||||
|
|
||||||
class W25QXXFlash {
|
class W25QXXFlash {
|
||||||
|
private:
|
||||||
|
static MarlinSPI mySPI;
|
||||||
public:
|
public:
|
||||||
void init(uint8_t spiRate);
|
void init(uint8_t spiRate);
|
||||||
static uint8_t spi_flash_Rec();
|
static uint8_t spi_flash_Rec();
|
||||||
|
@ -191,6 +191,9 @@
|
|||||||
#define FSMC_DMA_DEV DMA2
|
#define FSMC_DMA_DEV DMA2
|
||||||
#define FSMC_DMA_CHANNEL DMA_CH5
|
#define FSMC_DMA_CHANNEL DMA_CH5
|
||||||
|
|
||||||
|
#define TFT_CS_PIN FSMC_CS_PIN
|
||||||
|
#define TFT_RS_PIN FSMC_RS_PIN
|
||||||
|
|
||||||
#define TOUCH_BUTTONS_HW_SPI
|
#define TOUCH_BUTTONS_HW_SPI
|
||||||
#define TOUCH_BUTTONS_HW_SPI_DEVICE 2
|
#define TOUCH_BUTTONS_HW_SPI_DEVICE 2
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO
|
|||||||
exec_test $1 $2 "MKS Robin nano v1.2 Emulated DOGM FSMC"
|
exec_test $1 $2 "MKS Robin nano v1.2 Emulated DOGM FSMC"
|
||||||
|
|
||||||
#
|
#
|
||||||
# MKS Robin v2 nano LVGL SPI
|
# MKS Robin v2 nano Emulated DOGM SPI
|
||||||
# (Robin v2 nano has no FSMC interface)
|
# (Robin v2 nano has no FSMC interface)
|
||||||
#
|
#
|
||||||
use_example_configs Mks/Robin
|
use_example_configs Mks/Robin
|
||||||
|
69
buildroot/tests/mks_robin_nano35_stm32-tests
Normal file
69
buildroot/tests/mks_robin_nano35_stm32-tests
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Build tests for MKS Robin nano
|
||||||
|
# (STM32F1 genericSTM32F103VE)
|
||||||
|
#
|
||||||
|
|
||||||
|
# exit on first failure
|
||||||
|
set -e
|
||||||
|
|
||||||
|
#
|
||||||
|
# MKS Robin nano v1.2 Emulated DOGM FSMC
|
||||||
|
#
|
||||||
|
use_example_configs Mks/Robin
|
||||||
|
opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO
|
||||||
|
exec_test $1 $2 "MKS Robin nano v1.2 Emulated DOGM FSMC"
|
||||||
|
|
||||||
|
#
|
||||||
|
# MKS Robin v2 nano Emulated DOGM SPI
|
||||||
|
# (Robin v2 nano has no FSMC interface)
|
||||||
|
#
|
||||||
|
use_example_configs Mks/Robin
|
||||||
|
opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO_V2
|
||||||
|
opt_disable TFT_INTERFACE_FSMC
|
||||||
|
opt_enable TFT_INTERFACE_SPI
|
||||||
|
exec_test $1 $2 "MKS Robin v2 nano Emulated DOGM SPI"
|
||||||
|
|
||||||
|
#
|
||||||
|
# MKS Robin nano v1.2 LVGL FSMC
|
||||||
|
#
|
||||||
|
# use_example_configs Mks/Robin
|
||||||
|
# opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO
|
||||||
|
# opt_disable TFT_CLASSIC_UI TFT_COLOR_UI TOUCH_SCREEN TFT_RES_320x240
|
||||||
|
# opt_enable TFT_LVGL_UI TFT_RES_480x320
|
||||||
|
# exec_test $1 $2 "MKS Robin nano v1.2 LVGL FSMC"
|
||||||
|
|
||||||
|
#
|
||||||
|
# MKS Robin v2 nano LVGL SPI
|
||||||
|
# (Robin v2 nano has no FSMC interface)
|
||||||
|
#
|
||||||
|
# use_example_configs Mks/Robin
|
||||||
|
# opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO_V2
|
||||||
|
# opt_disable TFT_INTERFACE_FSMC TFT_COLOR_UI TOUCH_SCREEN TFT_RES_320x240
|
||||||
|
# opt_enable TFT_INTERFACE_SPI TFT_LVGL_UI TFT_RES_480x320
|
||||||
|
# exec_test $1 $2 "MKS Robin v2 nano LVGL SPI"
|
||||||
|
|
||||||
|
#
|
||||||
|
# MKS Robin v2 nano New Color UI 480x320 SPI
|
||||||
|
# (Robin v2 nano has no FSMC interface)
|
||||||
|
#
|
||||||
|
use_example_configs Mks/Robin
|
||||||
|
opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO_V2
|
||||||
|
opt_disable TFT_INTERFACE_FSMC TFT_RES_320x240
|
||||||
|
opt_enable TFT_INTERFACE_SPI TFT_RES_480x320
|
||||||
|
exec_test $1 $2 "MKS Robin v2 nano New Color UI 480x320 SPI"
|
||||||
|
|
||||||
|
#
|
||||||
|
# MKS Robin v2 nano LVGL SPI + TMC
|
||||||
|
# (Robin v2 nano has no FSMC interface)
|
||||||
|
#
|
||||||
|
# use_example_configs Mks/Robin
|
||||||
|
# opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO_V2
|
||||||
|
# opt_disable TFT_INTERFACE_FSMC TFT_COLOR_UI TOUCH_SCREEN TFT_RES_320x240
|
||||||
|
# opt_enable TFT_INTERFACE_SPI TFT_LVGL_UI TFT_RES_480x320
|
||||||
|
# opt_set X_DRIVER_TYPE TMC2209
|
||||||
|
# opt_set Y_DRIVER_TYPE TMC2209
|
||||||
|
# exec_test $1 $2 "MKS Robin v2 nano LVGL SPI + TMC"
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
restore_configs
|
Loading…
Reference in New Issue
Block a user