Skip to content

Commit

Permalink
Feather m0 support (#1)
Browse files Browse the repository at this point in the history
* featherM0 cmake & HardwareRateDriver

* Add basic timer, support for featherM0
  • Loading branch information
ethancheez authored May 24, 2023
1 parent 872c5cf commit 2908d3e
Show file tree
Hide file tree
Showing 280 changed files with 25,105 additions and 0 deletions.
32 changes: 32 additions & 0 deletions ATmega/ATmegaOs/AVR/IntervalTimer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <Os/IntervalTimer.hpp>
#include <Fw/Types/Assert.hpp>
#include <time.h>
#include <string.h>

namespace Os {

void IntervalTimer::getRawTime(RawTime& time) {
// TODO: need to set up timekeeping
U32 msec = 0; // millis();
U32 usec = 0; // micros();

time.upper = msec/1000;
time.lower = usec;
}

// Adapted from: http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html
// should be t1In - t2In
U32 IntervalTimer::getDiffUsec(const RawTime& t1In, const RawTime& t2In) {

RawTime result = {t1In.upper - t2In.upper,0};

if (t1In.lower < t2In.lower) {
result.upper -= 1; // subtract nsec carry to seconds
result.lower = t1In.lower + (1000000000 - t2In.lower);
} else {
result.lower = t1In.lower - t2In.lower;
}

return result.upper*1000000 + result.lower / 1000;
}
}
48 changes: 48 additions & 0 deletions ATmega/ATmegaOs/AVR/XMem.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* XMem.hpp:
*
* This file contains the setup sequence that is needed to enable the
* ATmega XMEM interface. It must be included in the main project
* file to be linked correctly in the final executable.
*
* Created on: March 25, 2020
* Author: Sterling Peet <sterling.peet@ae.gatech.edu>
*/

#include <avr/io.h>

#ifndef OS_AVR_XMEM_HPP_
#define OS_AVR_XMEM_HPP_

void xmem_init(void) __attribute__ ((naked, used, section(".init3")));

void xmem_init(void)
{
// Set up the XMEM interface
XMCRB = 0; // need all 64K. no pins released
#if defined(__AVR_ATmega128__)
MCUCR = _BV(SRE); // enable xmem, no wait states
#else
XMCRA = _BV(SRE); // enable xmem, no wait states
#endif

// set up the bank selector pins (address lines A16..A18)
// these are on pins 38,42,43 (PD7,PL7,PL6)
#if defined(__AVR_ATmega128__)
DDRD |= (_BV(PD5)|_BV(PD6)|_BV(PD7));
#else
DDRD |= _BV(PD7);
DDRL |= (_BV(PL6)|_BV(PL7));
#endif

// set the bank selector pins (address lines A16..A18)
// to zero only, we aren't doing fancy mem page swapping right now
#if defined(__AVR_ATmega128__)
PORTD &= ~(_BV(PD5)|_BV(PD6)|_BV(PD7));
#else
PORTD &= ~_BV(PD7);
PORTL &= ~(_BV(PL6)|_BV(PL7));
#endif
}

#endif /* OS_AVR_XMEM_HPP_ */
35 changes: 35 additions & 0 deletions ATmega/ATmegaOs/Arduino/IntervalTimer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <Os/IntervalTimer.hpp>
#include <Fw/Types/Assert.hpp>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <Arduino.h>

namespace Os {

void IntervalTimer::getRawTime(RawTime& time) {
// U32 msec = millis();
U32 usec = micros();

// This feels like a terrible kludge, but all we really
// care about is a difference in microseconds, right?
time.upper = 0; //msec/1000;
time.lower = usec;
}

// Adapted from: https://www.gnu.org/software/libc/manual/html_node/Calculating-Elapsed-Time.html
// should be t1In - t2In
U32 IntervalTimer::getDiffUsec(const RawTime& t1In, const RawTime& t2In) {

RawTime result = {t1In.upper - t2In.upper,0};

if (t1In.lower < t2In.lower) {
result.upper -= 1; // subtract nsec carry to seconds
result.lower = t1In.lower + (1000000 - t2In.lower);
} else {
result.lower = t1In.lower - t2In.lower;
}

return result.upper * 1000000 + result.lower;
}
}
57 changes: 57 additions & 0 deletions ATmega/ATmegaOs/Arduino/StreamLog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* LogArduinoStream:
*
* Implementation of Os::Log that defers to Arduino's Stream type. This allows for a hardware based
* stream capture. Note: in order to set the stream, the companion header Os/Arduino/StreamLog.hpp
* should be used.
*
* Created on: Apr 13, 2019
* Author: lestarch
*/

#include <Os/Log.hpp>
#include <ATmega/ATmegaOs/Arduino/StreamLog.hpp>

extern "C" {
#include <stdio.h>
#include <string.h>
}

namespace Os {
Stream* A_STREAM = NULL; // I love it when a plan comes together.
void setArduinoStreamLogHandler(Stream* stream) {
A_STREAM = stream;
}
Log::Log() {

// Register myself as a logger at construction time. If used in unison with LogDefault.cpp, this will
// automatically create this as a default logger.
this->registerLogger(this);
}
/**
* An Arduino Stream implementation of the Os::Log function. Essentially, this log message
* handler formats a message an sends it out to the serial port/Wire port or Arduino stream
* backing the stream object. This allows for a side-channel serial console.
*/
void Log::log(
const char* fmt,
POINTER_CAST a0,
POINTER_CAST a1,
POINTER_CAST a2,
POINTER_CAST a3,
POINTER_CAST a4,
POINTER_CAST a5,
POINTER_CAST a6,
POINTER_CAST a7,
POINTER_CAST a8,
POINTER_CAST a9
) {
char message[128];
// If stream is defined, then write to it.
if (A_STREAM != NULL) {
U32 used = snprintf(message, sizeof(message), fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
used = (used > sizeof(message)) ? sizeof(message) : used;
A_STREAM->write(message, used);
}
}
}
21 changes: 21 additions & 0 deletions ATmega/ATmegaOs/Arduino/StreamLog.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* StreamLog.hpp:
*
* A file defining the functions used to set and configure the Stream used in the Arduino Log::Os
* handler function.
*
* Created on: Apr 13, 2019
* Author: lestarch
*/
#ifndef OS_ARDUINO_STREAMLOG_HPP_
#define OS_ARDUINO_STREAMLOG_HPP_
#include <Arduino.h>

namespace Os {
/**
* Sets the global A_STREAM arduino stream used to log Arudino messages through a hardware "Steam"
* like UART or I2C.
*/
void setArduinoStreamLogHandler(Stream* stream);
}
#endif /* OS_ARDUINO_STREAMLOG_HPP_ */
76 changes: 76 additions & 0 deletions ATmega/ATmegaOs/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
####
# F prime CMakeLists.txt:
#
# SOURCE_FILES: combined list of source and autocoding files
# MOD_DEPS: (optional) module dependencies
#
####
cmake_minimum_required(VERSION 3.13)
cmake_policy(SET CMP0079 NEW)

# Basic module dependencies
set(MOD_DEPS
Fw/Cfg
Fw/Types
Fw/Logger
Utils/Hash
)
# Determine the platform specific source files to append:

string(TOLOWER "${CMAKE_SYSTEM_NAME}" CMAKE_SYSTEM_NAME_LOWER)

# Arduino additions
if (${CMAKE_SYSTEM_NAME_LOWER} STREQUAL "arduino")
set(SOURCE_FILES
# Common implementations
"${FPRIME_FRAMEWORK_PATH}/Os/TaskCommon.cpp"
"${FPRIME_FRAMEWORK_PATH}/Os/TaskString.cpp"
"${FPRIME_FRAMEWORK_PATH}/Os/QueueCommon.cpp"
"${FPRIME_FRAMEWORK_PATH}/Os/QueueString.cpp"
# Baremetal virtualization implementations
"${FPRIME_FRAMEWORK_PATH}/Os/Baremetal/Queue.cpp"
"${FPRIME_FRAMEWORK_PATH}/Os/Baremetal/Task.cpp"
"${FPRIME_FRAMEWORK_PATH}/Os/Baremetal/File.cpp"
"${FPRIME_FRAMEWORK_PATH}/Os/Baremetal/FileSystem.cpp"
"${FPRIME_FRAMEWORK_PATH}/Os/Baremetal/IntervalTimer.cpp"
"${FPRIME_FRAMEWORK_PATH}/Os/Baremetal/Mutex.cpp"
# Non-OS based queue implementations
"${FPRIME_FRAMEWORK_PATH}/Os/Pthreads/BufferQueueCommon.cpp"
"${FPRIME_FRAMEWORK_PATH}/Os/Pthreads/FIFOBufferQueue.cpp"
# From this package: an interval timer and a stream-log timer
"${CMAKE_CURRENT_LIST_DIR}/Arduino/IntervalTimer.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Arduino/StreamLog.cpp"
)
# AVR platform additions
elseif(${CMAKE_SYSTEM_NAME_LOWER} STREQUAL "avr")
set(SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/AVR/IntervalTimer.cpp")
endif()

register_fprime_module()


####
# Dependency Melding:
#
# In short, this Os layer depends on the framework's Os layer and vise-versa. Effectively it is one
# library built in two halves, the framework base, and this add on. Here we make the link pointers
# depend on one another forming a (weak) circular dependency. This is allowed in CMake 3.13 and
# newer.
####
if (${CMAKE_SYSTEM_NAME_LOWER} STREQUAL "arduino")
add_dependencies(Os ATmega_ATmegaOs)
target_link_libraries(Os ATmega_ATmegaOs)
target_link_libraries(ATmega_ATmegaOs Os)
endif()

# Add Arduino dependency
if(${CMAKE_SYSTEM_NAME_LOWER} STREQUAL "arduino")
get_module_name(${CMAKE_CURRENT_LIST_DIR})
add_arduino_dependency("${MODULE_NAME}")
endif()

# Add AVR dependency
if(${CMAKE_SYSTEM_NAME_LOWER} STREQUAL "avr")
get_module_name(${CMAKE_CURRENT_LIST_DIR})
add_avr_dependency("${MODULE_NAME}")
endif()
8 changes: 8 additions & 0 deletions ATmega/ATmegaTypes/AVR/StandardTypes.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

#define NAME_MAX 64
#define PATH_MAX 128

extern "C" {
#include <stdint.h>
#include <stdlib.h>
} // extern "C"
6 changes: 6 additions & 0 deletions ATmega/ATmegaTypes/Arduino/StandardTypes.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <stdint.h>
#define NAME_MAX 255
typedef int TaskIdRepr;
#define FPRIME_OVERRIDE_NATIVE_TYPES
typedef int32_t NATIVE_INT_TYPE;
typedef uint32_t NATIVE_UINT_TYPE;
3 changes: 3 additions & 0 deletions ATmega/ATmegaTypes/cstdarg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
extern "C" {
#include <stdarg.h>
} // extern "C"
3 changes: 3 additions & 0 deletions ATmega/ATmegaTypes/cstdio
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
extern "C" {
#include <stdio.h>
} // extern "C"
3 changes: 3 additions & 0 deletions ATmega/ATmegaTypes/cstring
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
extern "C" {
#include <string.h>
} // extern "C"
50 changes: 50 additions & 0 deletions ATmega/Drv/ATmegaAdcDriver/ATmegaAdcDriverComponentAi.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>

<?xml-model href="../../../fprime/Autocoders/Python/default/schema/ISF/component_schema.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>

<component name="ATmegaAdcDriver" kind="passive" namespace="Drv">

<import_port_type>Svc/Sched/SchedPortAi.xml</import_port_type>
<import_port_type>ATmega/Drv/U16Array/U16ArrayPortAi.xml</import_port_type>


<comment>ATmega ADC reader component.</comment>

<ports>
<port name = "tlmSched" data_type = "Svc::Sched" kind="sync_input">
<comment>
Schedule from rate group to determine when to take readings and report
</comment>
</port>
<port name = "Report" data_type = "U16Array" kind="output" max_number="10">
<comment>
Sends ADC reading multiplied by gains to components which use them
</comment>
</port>
</ports>
<telemetry>
<channel id="0" name="ADC_CNTS" data_type="U16*">
<comment>
Pointer to raw ADC counts array
</comment>
</channel>
<channel id="1" name="ADC_VAL" data_type="U16*">
<comment>
Pointer to ADC readings multiplied by gains
</comment>
</channel>
</telemetry>
<!-- TODO: Figure out why parameters won't parse -->
<!-- <parameters>
<parameter id="0" set_opcode="10" save_opcode="11" name="SCALE" data_type="U16" default="1">
<comments>
Scale value to multiply by ADC reading before reporting to external components
</comments>
</parameter>
<parameter id="1" set_opcode="12" save_opcode="13" name="OFFSET" data_type="I16" default="0">
<comments>
Offset to add to ADC reading AFTER multiplying by SCALE and before reporting to external components
</comments>
</parameter>
</parameters> -->
</component>
Loading

0 comments on commit 2908d3e

Please sign in to comment.