Skip to content

Core api update interrupt #343

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
May 12, 2025
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8499aa7
cores/xmc/: Add Uart class for Serial implementation.
LinjingZhang Apr 7, 2025
59f347b
variants/: Adapt pins_arduino.h for xmc4700.
LinjingZhang Apr 7, 2025
83895b3
cores/xmc: Adapt Serial after using namespace arduino.
LinjingZhang Apr 9, 2025
66d5f7e
arduino-core-tests/: Update the core test to newest main.
LinjingZhang Apr 10, 2025
eb65b85
/cores/xmc/Uart.h: Fix typo.
LinjingZhang Apr 10, 2025
5fdc74a
cores/xmc: Fix Uart bug, only use ringbuffer for rx.
LinjingZhang Apr 17, 2025
79a1e99
pins_arduino.h: Update for XMC4700_Relax_Kit.
LinjingZhang Apr 17, 2025
f39bc19
cores/xmc/: Add Interrupt Implementation.
dineshgit411 May 5, 2025
03f2668
variants/: Adapt pins_arduino.h for XMC4700.
dineshgit411 May 5, 2025
ca9062d
tests/: Modify pin numbers for interrupts.
dineshgit411 May 5, 2025
e3daa78
tests/arduino-core-tests/: Add submodule of tests.
dineshgit411 May 5, 2025
f11dfa0
workflows/: Comment library examples.
dineshgit411 May 6, 2025
ed08fd9
arduino-core-tests/: Update test case for interrupt.
dineshgit411 May 7, 2025
46bd28c
compile-platform-examples: Comment library examples.
dineshgit411 May 6, 2025
6852bae
arduino-core-tests: Add submodules.
dineshgit411 May 7, 2025
03eb83d
.github/workflows: Comment library examples.
dineshgit411 May 7, 2025
4343d53
arduino-core-tests/: Update test case for interrupt.
dineshgit411 May 7, 2025
654f138
compile-platform-examples: Comment library examples.
dineshgit411 May 6, 2025
f004b37
cores/xmc/: Removed uart files.
dineshgit411 May 9, 2025
7da4d7d
cores/xmc/: Comment serial functions.
dineshgit411 May 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions cores/xmc/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@

#ifdef __cplusplus
using namespace arduino;

extern "C" {
#endif

Expand Down Expand Up @@ -342,12 +341,12 @@ extern void loop(void);

#ifdef __cplusplus
} // extern "C"
// #include "Tone.h"
// #include "WMath.h"
// #include "Tone.h"
// #include "WMath.h"
#include "Uart.h"
#endif // __cplusplus

// #include "Print.h"
// #include "HardwareSerial.h"

//****************************************************************************
// @Board Variant Includes
Expand Down
156 changes: 156 additions & 0 deletions cores/xmc/Uart.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/*
Copyright (c) 2011 Arduino. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

//****************************************************************************
// @Project Includes
//****************************************************************************
#include "Uart.h"
#include "Arduino.h"

//****************************************************************************
// @Local Functions
//****************************************************************************

// Constructors ////////////////////////////////////////////////////////////////

Uart::Uart(XMC_UART_t *xmc_uart_config, RingBuffer *rx_buffer) {
_XMC_UART_config = xmc_uart_config;
_rx_buffer = rx_buffer;
}

// Public Methods //////////////////////////////////////////////////////////////

void Uart::begin(unsigned long baud) { begin(baud, SERIAL_8N1); }

void Uart::begin(unsigned long baud, unsigned short config) {
begin(baud, static_cast<XMC_UART_MODE_t>(config));
}

void Uart::begin(unsigned long baud, XMC_UART_MODE_t config) {
XMC_UART_CH_CONFIG_t uart_ch_config;
uart_ch_config.oversampling = 0; // Must be 0 or valid oversample for baud rate calculations
uart_ch_config.baudrate = baud;
uart_ch_config.data_bits = (uint8_t)(config & 0x00fU);
uart_ch_config.frame_length = uart_ch_config.data_bits; // Set same as data bits length
uart_ch_config.parity_mode = (XMC_USIC_CH_PARITY_MODE_t)(config & ~0xffU);
uart_ch_config.stop_bits = (uint8_t)((config & 0x0f0U) >> 4);

XMC_UART_CH_Init(_XMC_UART_config->channel, &uart_ch_config);

// dx0 is UART RX: source must be set
XMC_USIC_CH_SetInputSource(_XMC_UART_config->channel, XMC_USIC_CH_INPUT_DX0,
_XMC_UART_config->input_source_dx0);

// Additional input multiplexing
// Check if dx1 is used
if (_XMC_UART_config->input_source_dx1 != XMC_INPUT_INVALID)
XMC_USIC_CH_SetInputSource(_XMC_UART_config->channel, XMC_USIC_CH_INPUT_DX1,
_XMC_UART_config->input_source_dx1);

// Check if dx2 is used
if (_XMC_UART_config->input_source_dx2 != XMC_INPUT_INVALID)
XMC_USIC_CH_SetInputSource(_XMC_UART_config->channel, XMC_USIC_CH_INPUT_DX2,
_XMC_UART_config->input_source_dx2);

// Check if dx3 is used
if (_XMC_UART_config->input_source_dx3 != XMC_INPUT_INVALID)
XMC_USIC_CH_SetInputSource(_XMC_UART_config->channel, XMC_USIC_CH_INPUT_DX3,
_XMC_UART_config->input_source_dx3);

XMC_UART_CH_EnableEvent(_XMC_UART_config->channel, XMC_UART_CH_EVENT_ALTERNATIVE_RECEIVE |
XMC_UART_CH_EVENT_STANDARD_RECEIVE);
XMC_USIC_CH_SetInterruptNodePointer(_XMC_UART_config->channel,
XMC_USIC_CH_INTERRUPT_NODE_POINTER_RECEIVE,
_XMC_UART_config->irq_service_request);
XMC_USIC_CH_SetInterruptNodePointer(_XMC_UART_config->channel,
XMC_USIC_CH_INTERRUPT_NODE_POINTER_ALTERNATE_RECEIVE,
_XMC_UART_config->irq_service_request);
XMC_USIC_CH_SetInterruptNodePointer(_XMC_UART_config->channel,
XMC_USIC_CH_INTERRUPT_NODE_POINTER_TRANSMIT_BUFFER,
_XMC_UART_config->irq_service_request);
NVIC_SetPriority(_XMC_UART_config->irq_num, 3);
NVIC_EnableIRQ(_XMC_UART_config->irq_num);

XMC_UART_CH_Start(_XMC_UART_config->channel);

// TX pin setup put here to avoid startup corrupted characters being first sent
XMC_GPIO_Init(_XMC_UART_config->tx.port, _XMC_UART_config->tx.pin,
&(_XMC_UART_config->tx_config));

XMC_GPIO_Init(_XMC_UART_config->rx.port, _XMC_UART_config->rx.pin,
&(_XMC_UART_config->rx_config));
}

void Uart::end(void) {
// Wait for any outstanding data to be sent
flush();
// Disable UART interrupt in NVIC
NVIC_DisableIRQ(_XMC_UART_config->irq_num);
// Clear any received data after stopping interrupts
_rx_buffer->clear();
}

void Uart::setInterruptPriority(uint32_t priority) {
NVIC_SetPriority(_XMC_UART_config->irq_num, priority & 0x03);
}

uint32_t Uart::getInterruptPriority() { return NVIC_GetPriority(_XMC_UART_config->irq_num); }

int Uart::available(void) { return _rx_buffer->available(); }

int Uart::availableForWrite(void) {
return 1;
} // TODO: there are no tx buffer so we awaly have 1 byte available

int Uart::peek(void) { return _rx_buffer->peek(); }

int Uart::read(void) { return _rx_buffer->read_char(); }

void Uart::flush(void) {
while (XMC_USIC_CH_GetTransmitBufferStatus(_XMC_UART_config->channel) ==
XMC_USIC_CH_TBUF_STATUS_BUSY) {
};
}

size_t Uart::write(const uint8_t uc_data) {
// For sending, write immediately
// This API already have a check for available buffer
XMC_UART_CH_Transmit(_XMC_UART_config->channel, uc_data);
return 1;
}

void Uart::IrqHandler(void) {
// Receive data Interrupt handler
uint32_t status = XMC_UART_CH_GetStatusFlag(_XMC_UART_config->channel);

// Did we receive data?
if ((status & (XMC_UART_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION |
XMC_UART_CH_STATUS_FLAG_RECEIVE_INDICATION)) != 0U) {
XMC_UART_CH_ClearStatusFlag(_XMC_UART_config->channel,
(XMC_UART_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION |
XMC_UART_CH_STATUS_FLAG_RECEIVE_INDICATION));

while (_XMC_UART_config->channel->RBUFSR &
(USIC_CH_RBUFSR_RDV0_Msk | USIC_CH_RBUFSR_RDV1_Msk))
_rx_buffer->store_char(XMC_UART_CH_GetReceivedData(_XMC_UART_config->channel));
}
}

//****************************************************************************
// END OF FILE
//****************************************************************************
133 changes: 133 additions & 0 deletions cores/xmc/Uart.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
Copyright (c) 2011 Arduino. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once

//****************************************************************************
// @External Prototypes
//****************************************************************************

#include "Arduino.h"
//****************************************************************************
// @Project Includes
//****************************************************************************
#include "api/HardwareSerial.h"
#include "api/RingBuffer.h"

//****************************************************************************
// @Typedefs
//****************************************************************************
// Define config for Serial.begin(baud, config);
#undef SERIAL_5N1
#undef SERIAL_6N1
#undef SERIAL_7N1
#undef SERIAL_8N1
#undef SERIAL_5N2
#undef SERIAL_6N2
#undef SERIAL_7N2
#undef SERIAL_8N2
#undef SERIAL_5E1
#undef SERIAL_6E1
#undef SERIAL_7E1
#undef SERIAL_8E1
#undef SERIAL_5E2
#undef SERIAL_6E2
#undef SERIAL_7E2
#undef SERIAL_8E2
#undef SERIAL_5O1
#undef SERIAL_6O1
#undef SERIAL_7O1
#undef SERIAL_8O1
#undef SERIAL_5O2
#undef SERIAL_6O2
#undef SERIAL_7O2
#undef SERIAL_8O2

typedef enum XMC_UART_MODE {
SERIAL_5N1 = 0x15 | XMC_USIC_CH_PARITY_MODE_NONE,
SERIAL_6N1 = 0x16 | XMC_USIC_CH_PARITY_MODE_NONE,
SERIAL_7N1 = 0x17 | XMC_USIC_CH_PARITY_MODE_NONE,
SERIAL_8N1 = 0x18 | XMC_USIC_CH_PARITY_MODE_NONE,
SERIAL_5N2 = 0x25 | XMC_USIC_CH_PARITY_MODE_NONE,
SERIAL_6N2 = 0x26 | XMC_USIC_CH_PARITY_MODE_NONE,
SERIAL_7N2 = 0x27 | XMC_USIC_CH_PARITY_MODE_NONE,
SERIAL_8N2 = 0x28 | XMC_USIC_CH_PARITY_MODE_NONE,
SERIAL_5E1 = 0x15 | XMC_USIC_CH_PARITY_MODE_EVEN,
SERIAL_6E1 = 0x16 | XMC_USIC_CH_PARITY_MODE_EVEN,
SERIAL_7E1 = 0x17 | XMC_USIC_CH_PARITY_MODE_EVEN,
SERIAL_8E1 = 0x18 | XMC_USIC_CH_PARITY_MODE_EVEN,
SERIAL_5E2 = 0x25 | XMC_USIC_CH_PARITY_MODE_EVEN,
SERIAL_6E2 = 0x26 | XMC_USIC_CH_PARITY_MODE_EVEN,
SERIAL_7E2 = 0x27 | XMC_USIC_CH_PARITY_MODE_EVEN,
SERIAL_8E2 = 0x28 | XMC_USIC_CH_PARITY_MODE_EVEN,
SERIAL_5O1 = 0x15 | XMC_USIC_CH_PARITY_MODE_ODD,
SERIAL_6O1 = 0x16 | XMC_USIC_CH_PARITY_MODE_ODD,
SERIAL_7O1 = 0x17 | XMC_USIC_CH_PARITY_MODE_ODD,
SERIAL_8O1 = 0x18 | XMC_USIC_CH_PARITY_MODE_ODD,
SERIAL_5O2 = 0x25 | XMC_USIC_CH_PARITY_MODE_ODD,
SERIAL_6O2 = 0x26 | XMC_USIC_CH_PARITY_MODE_ODD,
SERIAL_7O2 = 0x27 | XMC_USIC_CH_PARITY_MODE_ODD,
SERIAL_8O2 = 0x28 | XMC_USIC_CH_PARITY_MODE_ODD
} XMC_UART_MODE_t;

//****************************************************************************
// @Class Definitionsw
//****************************************************************************
class Uart : public HardwareSerial {
public:
XMC_UART_t *_XMC_UART_config;
Uart(XMC_UART_t *xmc_uart_config, RingBuffer *rx_buffer);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice if we could create a XMC_UART object by passing valid UART pins like UART(pin_tx, pin_rx, pin_cts, pin_rts).
Not sure how affordable is it to implement based on the xmc_lib API.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be possible. need to modify pins_arduino.h

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one probably needs more work than we want to take now. So we can create a ticket for this for the future.


void begin(unsigned long);
void begin(unsigned long baudrate, uint16_t config) override;
void begin(unsigned long, XMC_UART_MODE_t config);
void end();
int available(void);
int availableForWrite(void);
int peek(void);
int read(void);
void flush(void);

// virtual size_t readBytes(char *buffer, size_t length) ; // read chars from stream into buffer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleanup stale code or comment whey it is commented.

// virtual size_t readBytes(uint8_t *buffer, size_t length) ;

size_t write(const uint8_t);

// virtual size_t write(const uint8_t *buffer, size_t size) ;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some or all of these functions are already provided by parent classes. Unless they are different, we don´t need to rewrite them.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can remove the inline functions, here is the reason I keep it:
I did not rewrite any function except implement write(). But the XMC4Arduino doesn't implement size_t write(const uint8_t *buffer, size_t size), just using the default implementation of Print class. But what about types other than uint8? That is why inline functions are added, it just truncates all inputs to 8-bit bytes.

If I had to severely rewrite the entire uart module, I would change this part

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For all the other types you would use the print() function. And these are handled here:
https://github.com/arduino/ArduinoCore-API/blob/master/api/Print.h#L64-L91

The overloaded print() functions will eventually call write().
Why write() would need to handled that duplicating the behavior or write()?
Why do you have to rewrite the entire module?

We need to provide mandatorily:
virtual size_t write(uint8_t) = 0;
And optionally, and many times convenient:
virtual size_t write(const uint8_t *buffer, size_t size);

inline size_t write(unsigned long n) { return write((uint8_t)n); }

inline size_t write(long n) { return write((uint8_t)n); }

inline size_t write(unsigned int n) { return write((uint8_t)n); }

inline size_t write(int n) { return write((uint8_t)n); }

using Print::write; // pull in write(str) and write(buf, size) from Print

operator bool() { return true; }

void setInterruptPriority(uint32_t priority);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these functions public ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi juan, for uart we have another one branch please check other PR which is created by linjing , kindly do review also that one.

i will remove the rewrite functions and let me test again for UART implementation

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, i mean, if that is part of another PR it is fine.
All the uart related comments should be taken in that PR.
If this version is sufficient to get the output of the tests, that´s fine :)

uint32_t getInterruptPriority();

void IrqHandler(void);

private:
RingBuffer *_rx_buffer;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not to have the RingBuffer object instead of a pointer?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had the same question. Of course we can change it, but we also need to change all the declarations inside pins_arduino.h.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless a good reason not to be a private member of the class. Yes please.
Each UART instance handles its own buffer. The UART API public does not need to expose any of that or?

};

extern Uart Serial;
extern Uart Serial1;
Loading
Loading