текучка
This commit is contained in:
1 parent
b920713163
commit
47ff1ce4eb
7 files changed
+135
-80
No files matched your search
@@ -4,6 +4,7 @@
|
||||
#include "pins_arduino.h"
|
||||
#include "wiring_digital.h"
|
||||
#include "WInterrupts.h"
|
||||
#include "wiring_LL.h"
|
||||
|
||||
extern void ErrorMsgHandler(const char * msg);
|
||||
|
||||
@@ -100,33 +101,27 @@ void detachInterrupt(uint8_t interruptNum)
|
||||
void disableInterrupt(uint8_t interruptNum)
|
||||
{
|
||||
if(interruptNum < EXTERNAL_NUM_INTERRUPTS)
|
||||
{
|
||||
int irq_line_num = interruptToGpioIntLine(interruptNum) >> GPIO_IRQ_LINE_S;
|
||||
// disable gpio interrupt line
|
||||
GPIO_IRQ->ENABLE_CLEAR = (1 << irq_line_num);
|
||||
}
|
||||
GPIO_IRQ_LINE_DISABLE(interruptToGpioIntLine(interruptNum));
|
||||
}
|
||||
|
||||
// enable single interrupt
|
||||
void enableInterrupt(uint8_t interruptNum)
|
||||
{
|
||||
if(interruptNum < EXTERNAL_NUM_INTERRUPTS)
|
||||
{
|
||||
int irq_line_num = interruptToGpioIntLine(interruptNum) >> GPIO_IRQ_LINE_S;
|
||||
// enable gpio interrupt line
|
||||
GPIO_IRQ->ENABLE_SET = (1 << irq_line_num);
|
||||
}
|
||||
GPIO_IRQ_LINE_ENABLE(interruptToGpioIntLine(interruptNum));
|
||||
}
|
||||
|
||||
// common gpio interrupt handler
|
||||
void gpio_interrupts_handler(void) __attribute__((noinline, section(".ram_text")));
|
||||
void gpio_interrupts_handler(void)
|
||||
{
|
||||
// go through all the interrupts and call the handler for the triggered line
|
||||
for (uint8_t i = 0; i < EXTERNAL_NUM_INTERRUPTS; i++)
|
||||
{
|
||||
if (HAL_GPIO_LineInterruptState(interruptToGpioIntLine(i)))
|
||||
if (GPIO_IRQ_LINE_STATE(interruptToGpioIntLine(i)))
|
||||
intFunc[i]();
|
||||
}
|
||||
|
||||
HAL_GPIO_ClearInterrupts();
|
||||
GPIO_IRQ_CLEAR_ALL();
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
#include "mik32_hal_irq.h"
|
||||
|
||||
#include "mik32_hal_gpio.h"
|
||||
|
||||
|
||||
// isr functions
|
||||
extern void serial_handler_wrapper(uint8_t uartNumInt);
|
||||
extern void gpio_interrupts_handler(void);
|
||||
@@ -11,16 +8,13 @@ void __attribute__((weak)) wire_handler_wrapper(void)
|
||||
{
|
||||
// dummy function for case when wire library is not in use
|
||||
}
|
||||
extern void softSerial_handler_wrapper(void);
|
||||
|
||||
// ---------------------------------------------- //
|
||||
void __attribute__((noinline, section(".ram_text"))) trap_handler(void)
|
||||
{
|
||||
((GPIO_0)->CLEAR = (GPIO_PIN_0));
|
||||
// gpio interrupt
|
||||
if (EPIC_CHECK_GPIO_IRQ())
|
||||
// gpio_interrupts_handler();
|
||||
softSerial_handler_wrapper();
|
||||
gpio_interrupts_handler();
|
||||
|
||||
// tone timer interrupt
|
||||
if (EPIC_CHECK_TIMER16_1())
|
||||
@@ -40,5 +34,4 @@ void __attribute__((noinline, section(".ram_text"))) trap_handler(void)
|
||||
|
||||
// reset all interrupts
|
||||
HAL_EPIC_Clear(0xFFFFFFFF);
|
||||
((GPIO_0)->SET = (GPIO_PIN_0));
|
||||
}
|
||||
@@ -23,7 +23,11 @@
|
||||
// ----------------- GPIO IRQ ----------------- //
|
||||
#define GPIO_IRQ_LINE_ENABLE(lineMask) ( GPIO_IRQ->ENABLE_SET = (1 << (lineMask >> GPIO_IRQ_LINE_S)) )
|
||||
#define GPIO_IRQ_LINE_DISABLE(lineMask) ( GPIO_IRQ->ENABLE_CLEAR = (1 << (lineMask >> GPIO_IRQ_LINE_S)) )
|
||||
#define GPIO_IRQ_CLEAR_ALL() (GPIO_IRQ->CLEAR = 0b11111111)
|
||||
#define GPIO_IRQ_LINE_STATE(lineMask) ((GPIO_IRQ->INTERRUPT & (1 << (lineMask >> GPIO_IRQ_LINE_S))) != 0)
|
||||
#define GPIO_IRQ_CLEAR_ALL() ( GPIO_IRQ->CLEAR = 0b11111111)
|
||||
|
||||
// ----------------- PIN CONFIG ----------------- //
|
||||
// return config of pin with pinShift(0...16) in portReg (config, pupd, ds for ports 0...2)
|
||||
#define PIN_GET_PAD_CONFIG(portReg, pinShift) ((PAD_CONFIG->portReg >> (pinShift<<1)) & 0b11)
|
||||
|
||||
#endif /* _WIRING_LL_H_ */
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Software serial multiple serial test
|
||||
|
||||
Receives from the two software serial ports,
|
||||
sends to the hardware serial port.
|
||||
|
||||
In order to listen on a software port, you call port.listen().
|
||||
When using two software serial ports, you have to switch ports
|
||||
by listen()ing on each one in turn. Pick a logical time to switch
|
||||
ports, like the end of an expected transmission, or when the
|
||||
buffer is empty. This example switches ports when there is nothing
|
||||
more to read from a port
|
||||
|
||||
The circuit:
|
||||
Two devices which communicate serially are needed.
|
||||
* First serial device's TX attached to digital pin 2(RX), RX to pin 6(TX)
|
||||
* Second serial device's TX attached to digital pin 8(RX), RX to pin 10(TX)
|
||||
|
||||
Note:
|
||||
Not all pins on the Elbear Ace-Uno support interrupts,
|
||||
so only the following can be used for RX:
|
||||
2, 3, 4, 5, 8, 9
|
||||
|
||||
created 18 Apr. 2011
|
||||
modified 19 March 2016
|
||||
by Tom Igoe
|
||||
based on Mikal Hart's twoPortRXExample
|
||||
|
||||
This example code is in the public domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
// software serial #1: RX = digital pin 2, TX = digital pin 6
|
||||
SoftwareSerial portOne(2, 6);
|
||||
|
||||
// software serial #2: RX = digital pin 8, TX = digital pin 10
|
||||
SoftwareSerial portTwo(8, 10);
|
||||
|
||||
void setup() {
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(115200);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for native USB port only
|
||||
}
|
||||
|
||||
// Start each software serial port
|
||||
portOne.begin(57600);
|
||||
portTwo.begin(57600);
|
||||
|
||||
portTwo.listen();
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// By default, the last initialized port is listening.
|
||||
// when you want to listen on a port, explicitly select it:
|
||||
portOne.listen();
|
||||
Serial.println("Data from port one:");
|
||||
// while there is data coming in, read it
|
||||
// and send to the hardware serial port:
|
||||
while (portOne.available() > 0) {
|
||||
char inByte = portOne.read();
|
||||
Serial.write(inByte);
|
||||
}
|
||||
|
||||
// blank line to separate data from the two ports:
|
||||
Serial.println();
|
||||
delay(2000);
|
||||
|
||||
// // Now listen on the second port
|
||||
// portTwo.listen();
|
||||
// // while there is data coming in, read it
|
||||
// // and send to the hardware serial port:
|
||||
// Serial.println("Data from port two:");
|
||||
// while (portTwo.available() > 0) {
|
||||
// char inByte = portTwo.read();
|
||||
// Serial.write(inByte);
|
||||
// }
|
||||
|
||||
// // blank line to separate data from the two ports:
|
||||
// Serial.println();
|
||||
// delay(2000);
|
||||
}
|
||||
@@ -89,15 +89,13 @@ void SoftwareSerial::recv() // .ram_text
|
||||
bool rxState = (bool)GPIO_READ_PIN((GPIO_TypeDef *)_receivePortRegister, (HAL_PinsTypeDef)_receiveBitMask);
|
||||
if (_inverse_logic ? rxState : !rxState)
|
||||
{
|
||||
// Disable further interrupts during reception, this prevents
|
||||
// triggering another interrupt directly after we return, which can
|
||||
// cause problems at higher baudrates.
|
||||
// Disable further interrupts during reception, this prevents triggering another interrupt
|
||||
// directly after we return, which can cause problems at higher baudrates.
|
||||
setRxIntMsk(false); // __always_inline__
|
||||
|
||||
// Wait approximately 1/2 of a bit width to "center" the sample
|
||||
if (_rx_delay_centering > 0)
|
||||
tunedDelay(_rx_delay_centering); // .ram_text
|
||||
GPIO_0->OUTPUT_ ^= GPIO_PIN_1;
|
||||
|
||||
// Read each of the 8 bits
|
||||
uint8_t data = 0;
|
||||
@@ -105,13 +103,9 @@ void SoftwareSerial::recv() // .ram_text
|
||||
{
|
||||
tunedDelay(_rx_delay_intrabit);
|
||||
data >>= 1;
|
||||
|
||||
GPIO_0->OUTPUT_ ^= GPIO_PIN_1;
|
||||
|
||||
if (GPIO_READ_PIN((GPIO_TypeDef *)_receivePortRegister, (HAL_PinsTypeDef)_receiveBitMask))
|
||||
data |= 0x80;
|
||||
}
|
||||
|
||||
if (_inverse_logic)
|
||||
data = ~data;
|
||||
|
||||
@@ -124,17 +118,13 @@ void SoftwareSerial::recv() // .ram_text
|
||||
_receive_buffer_tail = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
_buffer_overflow = true;
|
||||
}
|
||||
|
||||
// skip the stop bit
|
||||
tunedDelay(_rx_delay_stopbit);
|
||||
GPIO_0->OUTPUT_ ^= GPIO_PIN_1;
|
||||
|
||||
// Re-enable interrupts when we're sure to be inside the stop bit
|
||||
setRxIntMsk(true);
|
||||
|
||||
}
|
||||
GPIO_IRQ_CLEAR_ALL();
|
||||
}
|
||||
@@ -151,7 +141,7 @@ void SoftwareSerial::handle_interrupt() // .ram_text
|
||||
{
|
||||
if (active_object)
|
||||
{
|
||||
active_object->recv();
|
||||
active_object->recv(); // .ram_text
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,29 +177,33 @@ SoftwareSerial::~SoftwareSerial()
|
||||
|
||||
void SoftwareSerial::setTX(uint8_t tx)
|
||||
{
|
||||
// First configure then write because writing pin didn't work until config is applied
|
||||
// save pin and port info
|
||||
_transmitBitMask = (uint16_t)digitalPinToBitMask(tx);
|
||||
_transmitPortRegister = (uint32_t)digitalPinToPort(tx);
|
||||
// set state before tx pin initialization to prevent false start bit
|
||||
if (_inverse_logic)
|
||||
GPIO_CLEAR_PIN((GPIO_TypeDef *)_transmitPortRegister, (HAL_PinsTypeDef)_transmitBitMask);
|
||||
else
|
||||
GPIO_SET_PIN((GPIO_TypeDef *)_transmitPortRegister, (HAL_PinsTypeDef)_transmitBitMask);
|
||||
// init pin as output
|
||||
pinMode(tx, OUTPUT);
|
||||
digitalWrite(tx, _inverse_logic ? LOW : HIGH);
|
||||
_transmitBitMask = (uint16_t)digitalPinToBitMask(tx); // save tx bit mask
|
||||
_transmitPortRegister = (uint32_t)digitalPinToPort(tx); // save tx port adress
|
||||
}
|
||||
|
||||
void SoftwareSerial::setRX(uint8_t rx)
|
||||
{
|
||||
_receiveBitMask = (uint16_t)digitalPinToBitMask(rx); // save rx bit mask
|
||||
_receivePortRegister = (uint32_t)digitalPinToPort(rx); // save rx port adress
|
||||
if (!_inverse_logic)
|
||||
pinMode(rx, INPUT_PULLUP); // pullup for normal logic
|
||||
else
|
||||
pinMode(rx, INPUT);
|
||||
|
||||
// Save gpio_line for turning on/off interrupts
|
||||
// save pin, port and gpio_line info
|
||||
_receiveBitMask = (uint16_t)digitalPinToBitMask(rx);
|
||||
_receivePortRegister = (uint32_t)digitalPinToPort(rx);
|
||||
_int_maskLine = digitalPinToGpioIntLine(_receivePin);
|
||||
// Init interrupt line
|
||||
HAL_GPIO_InitInterruptLine((HAL_GPIO_Line_Config)digitalPinToGpioIntMux(_receivePin),
|
||||
_inverse_logic ? GPIO_INT_MODE_RISING : GPIO_INT_MODE_FALLING);
|
||||
GPIO_IRQ_LINE_DISABLE(_int_maskLine); // turn off int line (it turning on while line init)
|
||||
HAL_EPIC_MaskEdgeSet(HAL_EPIC_GPIO_IRQ_MASK); // turn on the mask in EPIC
|
||||
|
||||
// attach interrupt to rx pin if available
|
||||
attachInterrupt(digitalPinToInterrupt(_receivePin), softSerial_handler_wrapper, _inverse_logic ? RISING : FALLING);
|
||||
if (!_inverse_logic)
|
||||
// turn on pull up for rx if logic is not inverse
|
||||
HAL_GPIO_PinConfig((GPIO_TypeDef *)_receivePortRegister, (HAL_PinsTypeDef)_receiveBitMask,
|
||||
HAL_GPIO_MODE_GPIO_INPUT, HAL_GPIO_PULL_UP, HAL_GPIO_DS_2MA);
|
||||
// turn off int line for while (it turning on in attachInterrupt())
|
||||
GPIO_IRQ_LINE_DISABLE(_int_maskLine);
|
||||
}
|
||||
|
||||
uint32_t SoftwareSerial::subtract_cap(uint32_t num, uint16_t sub)
|
||||
@@ -235,10 +229,11 @@ void SoftwareSerial::begin(long speed)
|
||||
// Precalculate the various delays in number of ticks
|
||||
uint32_t bit_delay = F_CPU / speed;
|
||||
|
||||
// init tx
|
||||
setTX(_transmitPin);
|
||||
_tx_delay = subtract_cap(bit_delay, 35); // 1 bit delay while transmitting data
|
||||
|
||||
// Only setup rx when we have a valid INT for this pin
|
||||
// init rx only when we have a valid INT for this pin
|
||||
if (digitalPinToInterrupt(_receivePin) != NOT_AN_INTERRUPT)
|
||||
{
|
||||
// set pin config
|
||||
@@ -260,10 +255,6 @@ void SoftwareSerial::begin(long speed)
|
||||
|
||||
tunedDelay(_tx_delay); // if we were low this establishes the end
|
||||
|
||||
// todo убрать
|
||||
HAL_GPIO_PinConfig(GPIO_0, GPIO_PIN_0, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
|
||||
HAL_GPIO_PinConfig(GPIO_0, GPIO_PIN_1, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
|
||||
|
||||
listen();
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,13 @@ static const uint8_t SCL = PIN_WIRE_SCL;
|
||||
#define WIRE_FREQ_1000K 1000000
|
||||
|
||||
// interrupts
|
||||
extern const uint8_t interruptInfo[EXTERNAL_NUM_INTERRUPTS][3];
|
||||
extern uint8_t interruptInfo[EXTERNAL_NUM_INTERRUPTS][3];
|
||||
// determines the board pin number by interrupt number
|
||||
#define interruptToDigitalPin(interruptNum) (interruptInfo[interruptNum][0])
|
||||
// determines gpio interrupt line by interrupt number
|
||||
#define interruptToGpioIntLine(interruptNum) ((uint8_t)interruptInfo[interruptNum][1])
|
||||
// determines gpio interrupt mux by interrupt number
|
||||
#define interruptToGpioIntMux(interruptNum) ((uint8_t)interruptInfo[interruptNum][2])
|
||||
// determines interrupt number by the board pin number
|
||||
int8_t digitalPinToInterrupt(uint32_t digPinNumber);
|
||||
// determines interrupt number by the gpio interrupt line
|
||||
@@ -119,23 +125,8 @@ int8_t digitalPinToGpioIntMux(uint8_t digPinNumber);
|
||||
// determines gpio interrupt line by the board pin number
|
||||
int8_t digitalPinToGpioIntLine(uint8_t digPinNumber);
|
||||
|
||||
// determines the board pin number by interrupt number
|
||||
inline uint8_t interruptToDigitalPin(uint8_t interruptNum)
|
||||
{
|
||||
return interruptInfo[interruptNum][0];
|
||||
}
|
||||
|
||||
// determines gpio interrupt line by interrupt number
|
||||
inline uint8_t interruptToGpioIntLine(uint8_t interruptNum)
|
||||
{
|
||||
return (uint8_t)interruptInfo[interruptNum][1];
|
||||
}
|
||||
|
||||
// determines gpio interrupt mux by interrupt number
|
||||
inline uint8_t interruptToGpioIntMux(uint8_t interruptNum)
|
||||
{
|
||||
return (uint8_t)interruptInfo[interruptNum][2];
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "pins_arduino.h"
|
||||
#include "mik32_hal_adc.h"
|
||||
#include "wiring_analog.h"
|
||||
#include "wiring_LL.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -107,10 +108,6 @@ volatile uint32_t* portInputRegister(GPIO_TypeDef* GPIO_x)
|
||||
return &GPIO_x->STATE;
|
||||
}
|
||||
|
||||
// return config of pin with pinShift(0...16) in portReg (config, pupd, ds for ports 0...2)
|
||||
#define PIN_PAD_CONFIG(portReg, pinShift) ((PAD_CONFIG->portReg >> (pinShift<<1)) & 0b11)
|
||||
|
||||
|
||||
// ---------------------- ADC ---------------------- //
|
||||
// determines the ADC channel number by the board pin number
|
||||
uint32_t analogInputToChannelNumber(uint32_t PinNumber)
|
||||
@@ -168,9 +165,9 @@ bool digitalPinPwmIsOn(uint8_t digitalPin)
|
||||
uint8_t pinShift = pwmPinToGpioPinShift(digitalPin);
|
||||
|
||||
if (PWM_PIN_TO_PORT_NUMBER(digitalPin) == 0)
|
||||
config = PIN_PAD_CONFIG(PORT_0_CFG, pinShift);
|
||||
config = PIN_GET_PAD_CONFIG(PORT_0_CFG, pinShift);
|
||||
else
|
||||
config = PIN_PAD_CONFIG(PORT_1_CFG, pinShift);
|
||||
config = PIN_GET_PAD_CONFIG(PORT_1_CFG, pinShift);
|
||||
|
||||
if (config == 2)
|
||||
return true;
|
||||
@@ -216,9 +213,9 @@ HAL_TIMER32_CHANNEL_IndexTypeDef pwmPinToTimerChannel(uint32_t digPinNumber)
|
||||
}
|
||||
|
||||
// ---------------------- interrupts ---------------------- //
|
||||
// interrupt table
|
||||
// interrupt table is stored in ram to improve performance
|
||||
// index = interrupt number. In each row {digitalPinNumber, IntLineValue, IntMuxValue}
|
||||
const uint8_t interruptInfo[EXTERNAL_NUM_INTERRUPTS][3] =
|
||||
uint8_t interruptInfo[EXTERNAL_NUM_INTERRUPTS][3] =
|
||||
{
|
||||
{ 2, GPIO_LINE_2, GPIO_MUX_LINE_2_PORT0_10}, // INT0
|
||||
{ 3, GPIO_LINE_0, GPIO_MUX_LINE_0_PORT0_0}, // INT1
|
||||
@@ -281,7 +278,7 @@ void spi_onBegin(void)
|
||||
// because spi needs pin 1.3 for correct work
|
||||
|
||||
// replace config from 1.3 to 1.4
|
||||
uint8_t config = PIN_PAD_CONFIG(PORT_1_CFG, PIN_3_SHIFT);
|
||||
uint8_t config = PIN_GET_PAD_CONFIG(PORT_1_CFG, PIN_3_SHIFT);
|
||||
if (config == 0) // common gpio
|
||||
{
|
||||
// get info from pin gpio1.3 and set config to gpio1.4
|
||||
|
||||
Reference in new issue
Block a user