Commit bca88616 authored by Vincent van Beveren's avatar Vincent van Beveren

build lm32 implementation (not finished yet)

Signed-off-by: Vincent van Beveren's avatarVincent van Beveren <v.van.beveren@nikhef.nl>
parent be8bd102
**/*.o
**/*.a
doc/html
doc/latex
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.toolchain.gnu.cross.base.1715085401">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.cross.base.1715085401" moduleId="org.eclipse.cdt.core.settings" name="Default">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.cross.base.1715085401" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.cross.base.1715085401.2129613306" name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.543226004" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
<option id="cdt.managedbuild.option.gnu.cross.prefix.2083903150" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix"/>
<option id="cdt.managedbuild.option.gnu.cross.path.927128670" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.733130988" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
<builder id="cdt.managedbuild.builder.gnu.cross.1362464039" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross"/>
<tool id="cdt.managedbuild.tool.gnu.cross.c.compiler.127428408" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
<option id="gnu.c.compiler.option.preprocessor.def.symbols.1605705687" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="SFP_WRITE_SUPPORT"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1058506932" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.73750744" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1539050551" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.967550631" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.250184423" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1448353394" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.56032099" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
<tool id="cdt.managedbuild.tool.gnu.cross.assembler.732695470" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.436963226" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="arch-wrpc-lm32"/>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="inc"/>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="libsfp.null.2045100723" name="libsfp"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Default">
<resource resourceType="PROJECT" workspacePath="/libsfp"/>
</configuration>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1715085401;cdt.managedbuild.toolchain.gnu.cross.base.1715085401.2129613306;cdt.managedbuild.tool.gnu.cross.cpp.compiler.73750744;cdt.managedbuild.tool.gnu.cpp.compiler.input.1539050551">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1715085401;cdt.managedbuild.toolchain.gnu.cross.base.1715085401.2129613306;cdt.managedbuild.tool.gnu.cross.c.compiler.127428408;cdt.managedbuild.tool.gnu.c.compiler.input.1058506932">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
</cproject>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>libsfp</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="cdt.managedbuild.toolchain.gnu.cross.base.1715085401" name="Default">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorCygwin" console="false" env-hash="-339977209373872057" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorCygwin" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cygwin" parameter="lm32-elf-gcc ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
</project>
This diff is collapsed.
eclipse.preferences.version=1
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1715085401/append=true
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1715085401/appendContributed=true
This source diff could not be displayed because it is too large. You can view the blob instead.
# Configure default architecutre and compiler
ARCH ?= wrpc-lm32
CROSS_COMPILE ?= lm32-elf-
# Cross-compilation tool-set
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
.PHONY: all clean debug
# Target
TARGET = sfp
FULL_TARGET = lib$(TARGET).a
# include
INCLUDE_DIRS = inc arch-$(ARCH)
# CFLAGS to use. Both this Makefile (later) and app-makefile may grow CFLAGS
CFLAGS = $(USER_CFLAGS)
CFLAGS += -Wall -O2 -ggdb -fno-common -DSFP_WRITE_SUPPORT
CFLAGS += $(foreach includedir,$(INCLUDE_DIRS),-I$(includedir))
# Gather all source files in project
C_SRCS = $(wildcard src/*.c) $(wildcard arch-$(ARCH)/*.c)
C_OBJS = $(patsubst %.c, %.o, $(C_SRCS))
# The main target is the big object file.
all: debug $(FULL_TARGET)
%.o: %.c
echo "Compiling $< -> $@"
$(CC) $(CFLAGS) -c -o $@ "$<"
$(FULL_TARGET) : $(C_OBJS)
$(AR) r $@ $^
clean:
$(RM) $(C_OBJS) $(FULL_TARGET)
debug:
echo "C_SRCS=$(C_SRCS)"
echo "C_OBJS=$(C_OBJS)"
echo "CFLAGS=$(CFLAGS)"
\ No newline at end of file
/*
* wrpc_config.h
*
* Created on: 23 okt. 2017
* Author: vincentb
*/
#ifndef WRPC_CONFIG_H_
#define WRPC_CONFIG_H_
/**
* WRPC configuration file
*/
// ===========================================================================
// GPIO Configuration
// ===========================================================================
#define WB_GPIO_BASE_ADDRESS 0x00000000
#define WB_GPIO_PORT_COUNT 32
// ===========================================================================
// I2C Configuration
// ===========================================================================
#define WB_I2C_COUNT 3
// WR_I2C_MASTERS is a list of WR_I2C_MASTER items defiend as:
// WR_I2C_MASTER(INDEX, NAME, ADDRESS)
// Where:
// INDEX runs from 0 to WB_I2C_COUNT - 1
// NAME is the device name (e.g "I2C0", "I2C1", etc..)
// ADDRESS is the base address of the I2C device
#define WR_I2C_MASTERS \
WR_I2C_MASTER(0, "I2C0", 0x00000000) \
WR_I2C_MASTER(1, "I2C1", 0x00000000) \
WR_I2C_MASTER(2, "I2C2", 0x00000000)
// ===========================================================================
// SFP Configuration
// ===========================================================================
#define SFP_COUNT 1
// SFP_SLOTS: Defines the SFP slots
// SFP_SLOT(I2C_IDX, NAME, MOD_PRESENT_GPIO, RX_LOSS_GPIO, TX_FAULT_GPIO)
// Where:
// SFP_IDX Index of the I2C device
// NAME Human readable name of this slot
// MOD_PRESENT_GPIO Module present GPIO, or -1 if it does not exist
// RX_LOSS_GPIO RX loss GPIO, or -1 if it does not exist
// TX_FAULT_GPIO TX fault GPIO, or -1 if it does not exist
#define SFP_SLOTS \
SFP_SLOT(0, "SFP0", -1, -1, -1)
#endif /* WRPC_CONFIG_H_ */
/*
* wrpc_gpio.c
*
* Created on: 23 okt. 2017
* Author: vincentb
*/
#include "sfpgpio.h"
#include "wrpc_config.h"
SFP_STUB sfp_status_t gpio_set_pinmode(sfp_gpio_pin_t pin, gpio_pinmode_t mode)
{
if (pin >= WB_GPIO_PORT_COUNT) return SFP_STATUS_INVALID;
// TODO
return SFP_STATUS_OK;
}
SFP_STUB bool gpio_get_level(sfp_gpio_pin_t pin)
{
if (pin >= WB_GPIO_PORT_COUNT) return false;
// TODO
return false;
}
SFP_STUB void gpio_set_level(sfp_gpio_pin_t pin, bool level)
{
if (pin >= WB_GPIO_PORT_COUNT) return;
// TODO
}
/*
* wrpc_i2c.c
*
* Created on: 23 okt. 2017
* Author: vincentb
*/
#include "sfpi2c_prov.h"
#include "wrpc_config.h"
sfp_status_t sfp_i2c_mtx_lm32wb(struct sfp_prov_i2c_s * pi2c, sfp_i2c_mtx_op_t oper)
{
// for now, locking and unlocking is not suported.
return SFP_STATUS_OK;
}
sfp_status_t sfp_i2c_trx_lm32wb(struct sfp_prov_i2c_s * pi2c, uint8_t adr, sfp_i2c_trx_t * trx)
{
// TODO execute transaction
return SFP_STATUS_OK;
}
#define WR_I2C_MASTER(IDX, NAME, OFFSET) \
{ \
.pub = { .name = NAME }, \
.trx = sfp_i2c_trx_lm32wb, \
.mtx = sfp_i2c_mtx_lm32wb, \
.user0 = {.v_ptr = ((void *)OFFSET) }, \
.user1 = {.u32 = IDX }, \
},
static sfp_prov_i2c_t _i2c_devs[WB_I2C_COUNT] = {
WR_I2C_MASTERS
};
#undef WR_I2C_MASTER
SFP_STUB unsigned int sfp_i2c_count()
{
return WB_I2C_COUNT;
}
SFP_STUB sfp_status_t sfp_i2c_get(unsigned int idx, sfp_i2c_t ** i2cdev)
{
if (idx >= WB_I2C_COUNT) return SFP_STATUS_INVALID;
*i2cdev = &_i2c_devs[idx].pub;
return SFP_STATUS_OK;
}
/*
* wrpc_sfpmod.c
*
* Created on: 23 okt. 2017
* Author: vincentb
*/
#include "sfpmod_prov.h"
#include "wrpc_config.h"
/*
typedef struct sfp_prov_mod_s {
sfp_mod_t pub; //!< Public SFP module structure
sfp_mod_ee_rd_f ee_rd; //!< Eeprom read
sfp_mod_ee_wd_f ee_wr; //!< Eeprom write
sfp_mod_sts_f sts; //!< Get status
void * user; //!< Custom data object.
} sfp_prov_mod_t;
typedef struct sfp_comp_mod_s {
sfp_prov_mod_t prov; //!< Provider interface
sfp_i2c_t * i2c; //!< I2C bus pointer
sfp_mux_op_t mux0; //!< Mux level 0, if any
sfp_mux_op_t mux1; //!< Mux level 1, if any
sfp_gpio_pin_t tx_fault; //!< Tx fault GPIO, or SFP_GPIO_NONE
sfp_gpio_pin_t rx_loss; //!< Rx loss GPIO, or SFP_GPIO_NONE
sfp_gpio_pin_t mod_prsnt; //!< Module present GPIO, or SFP_GPIO_NONE
sfp_gpio_pin_t reserved; //!< Reserved
} sfp_comp_mod_t;
*/
#define SFP_SLOT(I2C_IDX, NAME, MOD_PRESENT_GPIO, RX_LOSS_GPIO, TX_FAULT_GPIO) \
{ \
.prov = { \
.pub = { .name = NAME }, \
.ee_rd = sfp_comp_mod_ee_rd, \
.ee_wr = sfp_comp_mod_ee_wr, \
.sts = sfp_comp_mod_sts, \
.user = { .u32 = I2C_IDX } \
}, \
.i2c = NULL, /* lazy init */ \
.mux0 = { .val = 0 }, \
.mux1 = { .val = 0 }, \
.tx_fault = TX_FAULT_GPIO, \
.rx_loss = RX_LOSS_GPIO, \
.mod_prsnt = MOD_PRESENT_GPIO \
},
// we'll need to initialize this dynamically
static sfp_comp_mod_t _modules[SFP_COUNT] = {
SFP_SLOTS
};
#undef SFP_SLOT
SFP_STUB unsigned int sfp_mod_count()
{
return SFP_COUNT;
}
/*!
* \brief Get the reference to a module at the specified index position.
*
* \param idx The index position, 0..sfp_mod_count() - 1 .
* \param module A pointer pointer which will be set to provider module
*
* \return A SFP_STATUS_* value. See \link sfp_status_t \endlink
*/
SFP_STUB sfp_status_t sfp_mod_get(unsigned int idx, sfp_mod_t ** module)
{
if (idx >= SFP_COUNT) return SFP_STATUS_INVALID;
// lazy init of I2C, as we can not call this at initialization time
if (_modules[idx].i2c == NULL)
{
sfp_i2c_t * i2c;
if (sfp_i2c_get(_modules[idx].prov.user.u32, &i2c) != SFP_STATUS_OK)
return SFP_STATUS_MODULE_CONFIG_ERROR;
_modules[idx].i2c = i2c;
}
*module = &_modules[idx].prov.pub;
return SFP_STATUS_OK;
}
/*!
* \file sfpcommon.h
*
* \brief Common types and structures
*
* \author Vincent van Beveren v.van.beveren[at]nikhef.nl
* \date 4 July 2017
*/
#ifndef SFPCOMMON_H_
#define SFPCOMMON_H_
#include <stdint.h>
//! Marker to indicate the function needs to be implemented by the architecture.
#define SFP_STUB
/*!
* \brief Return status
*/
typedef enum sfp_status_e {
SFP_STATUS_OK,
SFP_STATUS_ERROR, //!< Generic unspecifeid error
SFP_STATUS_INVALID, //!< Resource is invalid
SFP_STATUS_NOT_SUPPORTED, //!< Not supported operation
SFP_STATUS_MODULE_CONFIG_ERROR, //!< Some part of the module configuration is invalid
SFP_STATUS_RESOURCE_IN_USE //!< Can't execute operation, resource in use
} sfp_status_t;
/**
* Generic variant type object.
*/
typedef union sfp_variant_u {
void * v_ptr;
uint32_t u32;
} sfp_variant_t;
#endif /* SFPCOMMON_H_ */
/*!
* \file sfpgpio.h
*
* \brief Public GPIO header file
*
* \author Vincent van Beveren (v.van.beveren[at]nikhef.nl)
* \date 4 July 2017
*
* Currently there is no notion of a GPIO instance in this abstraction. Usually there is just one GPIO
* instance. Otherwise one should use the upper bits in the pin value to make the distinction.
*/
#ifndef SFPGPIO_H_
#define SFPGPIO_H_
#include "sfpcommon.h"
#include <stdint.h>
#include <stdbool.h>
/**
* Pin-mode configuration.
*/
typedef enum gpio_pinmode_e {
GPIO_PINMODE_INPUT,
GPIO_PINMODE_OUTPUT
} gpio_pinmode_t;
/**
* Definition of a GPIO pin
*/
typedef uint16_t sfp_gpio_pin_t;
/**
* PIN error.
*/
#define SFP_GPIO_NONE ((sfp_gpio_pin_t)0xFFFF)
/**
* Sets the pin mode.
*
* @param pin The pin
* @param mode The mode
*
*
* @retval SFP_STATUS_OK If all is Ok
* @retval SFP_STATUS_NOT_SUPPORTED If the the mode does not exist
* @retval SFP_STATUS_INVALID If the pin is does not exist.
*/
SFP_STUB sfp_status_t gpio_set_pinmode(sfp_gpio_pin_t pin, gpio_pinmode_t mode);
/**
* Get GPIO pin level.
*
* If this is an input, it is the level the pin reads.
* If this is an output, it is the level the pin was set on.
*
* If the pin does not exist, this returns false.
*
* @param pin The pin
*
* @retval true Pin level high
* @retval false Pin level low
*/
SFP_STUB bool gpio_get_level(sfp_gpio_pin_t pin);
/**
* Set GPIO pin level. Only useful for output.
*
* Function does nothing if pin does not exist.
*
* @param pin The pin
* @param level The level to set: true - high, false - low.
*/
SFP_STUB void gpio_set_level(sfp_gpio_pin_t pin, bool level);
#endif /* SFPGPIO_H_ */
/*!
* \file sfpi2c.h
*
* \brief User header file for I2C.
*
* \author Vincent van Beveren (v.van.beveren[at]nikhef.nl)
* \date 4 July 2017
*/
#ifndef SFPI2C_H_
#define SFPI2C_H_
#include "sfpcommon.h"
#include <stdint.h>
#include <stddef.h>
/*!
* \brief Generic I2C structure.
*/
typedef struct sfp_i2c_s {
const char * name; //!< I2C master name.
} sfp_i2c_t;
/*!
* I2C slave definition.
*/
typedef struct sfp_i2c_slave_s {
sfp_i2c_t * i2c; //!< I2C master device
uint8_t addr; //!< I2C slave address
} sfp_i2c_slave_t;
/*!
* \brief Define an I2C slave (I2C device + address)
*
* @param i2c I2C device
* @param addr Address
*/
static inline sfp_i2c_slave_t sfp_i2c_slave(sfp_i2c_t * i2c, uint8_t addr)
{
sfp_i2c_slave_t slave;
slave.i2c = i2c;
slave.addr = addr;
return slave;
}
/*!
* \brief Returns the number of I2C master devices.
*/
SFP_STUB unsigned int sfp_i2c_count();
/*!
* \brief Returns the I2C module at the given index.
*
* \param idx The index of the device to get range 0..sfp_i2c_count() - 1.
* \param i2cdev A pointer pointer to get to the I2C device structure.
*
* \return A SFP_STATUS_* value. See \link sfp_status_t \endlink.
*/
SFP_STUB sfp_status_t sfp_i2c_get(unsigned int idx, sfp_i2c_t ** i2cdev);
/*!
* \brief I2C mutex operation.
*/
typedef enum sfp_i2c_mtx_op_e {
SFP_I2C_MUX_LOCK, //!< Lock the I2C bus for usage by this module
SFP_I2C_MUX_UNLOCK //!< Unlock it.
} sfp_i2c_mtx_op_t;
/*!
* \brief Lock or unlock the mutex
*
* \param i2c The I2C master to lock or unlock
* \param The operation, one of SFP_I2C_MUX_*
*
* \return A SFP_STATUS_* value. See \link sfp_status_t \endlink.
*/
sfp_status_t sfp_i2c_mtx(sfp_i2c_t * i2c, sfp_i2c_mtx_op_t oper);
/**
* \brief I2C transaction structure.
*
* There are four types of operations:
*
* - WRITE - Write from buffer 0 to I2C bus.
* - READ - Read into buffer from I2C bus.
* - WRITE_READ - Write from the first buffer and read into the second
* - WRITE_WRITE - Write from the first buffer and write from the second.
* - EXISTS - For this operation no buffers need to be filled, just
* checks if its possible to read from this device.
*
* The first two operations can be use for simple, non registered chips like muxes or ADCs.
* The second two operations can be used for registered devices, in which the proper register or
* address must first be written. For example, reading 16 bytes from EEPROM address 0xBEEF can be
* done as follows:
*
* @code
* uint8_t addr[2] = { 0xBE, 0xEF };
* uint8_t data[16];
*
* sfp_i2c_trx_t trx = {
* I2C_TRX_OPER_WRITE_READ,
* {
* { addr, sizeof(addr) },
* { data, sizeof(data) }
* }
* }
*
* sfp_i2c_trx(I2C1, 0xAA, &trx);
* @endcode
*
*/
typedef struct sfp_i2c_trx_s {
enum {
I2C_TRX_OPER_READ, //!< Read into buf[0]
I2C_TRX_OPER_WRITE, //!< Write from buf[0]
I2C_TRX_OPER_WRITE_READ, //!< Write from buf[0] and read into buf[1]
I2C_TRX_OPER_WRITE_WRITE, //!< Write from buf[0] and write from buf[1]
I2C_TRX_OPER_EXISTS //!< Simple existence check by checking for an ACK on read. No buffers used.
} oper; //!< Operation(s) to perform.
struct {
uint8_t * ptr; //!< Pointer to buffer to read or fill
size_t len; //!< Length of buffer to read or fill
} buf[2]; //!< Two buffers
} sfp_i2c_trx_t;
/*!
*
* \brief Execute an I2C transaction.
*
* \see sfp_i2c_trx_t
*
* \param slave The I2C slave
* \param trx A pointer to a transaction object
*
* \return A SFP_STATUS_* value. See \link sfp_status_t \endlink.
*/
sfp_status_t sfp_i2c_trx(sfp_i2c_slave_t * slave, sfp_i2c_trx_t * trx);
/*!
* I2C memory device read with 8 bit address space.
*/
static inline sfp_status_t sfp_i2c_a8_rd(sfp_i2c_slave_t * slave, uint8_t reg, uint8_t * data, size_t count)
{
sfp_i2c_trx_t trx = {
I2C_TRX_OPER_WRITE_READ,
{
{&reg, 1 },
{data, count }
}
};
return sfp_i2c_trx(slave, &trx);
}
/**
* I2C memory device write with 8 bit address space.
*/
static inline sfp_status_t sfp_i2c_a8_wr(sfp_i2c_slave_t * slave, uint8_t reg, uint8_t * data, size_t count)
{
sfp_i2c_trx_t trx = {
I2C_TRX_OPER_WRITE_READ,
{
{ &reg, 1 },
{ data, count }
}
};
return sfp_i2c_trx(slave, &trx);
}
static inline sfp_status_t sfp_i2c_wr(sfp_i2c_slave_t * slave, uint8_t * data, size_t count)
{
sfp_i2c_trx_t trx = {
I2C_TRX_OPER_WRITE,
{
{ data, count }
}
};
return sfp_i2c_trx(slave, &trx);
}
#endif /* SFPI2C_H_ */
/*!
* \file sfpi2c_prov.h
*
* \brief Architecture providers implementors header file for I2C.
*
* \author Vincent van Beveren (v.van.beveren[at]nikhef.nl)
* \date 4 July 2017
*/
#ifndef SFPI2C_PROV_H_
#define SFPI2C_PROV_H_
#include "sfpi2c.h"
/*!
* Provider I2C structure.
*/
struct sfp_prov_i2c_s;
/*!
* Callback to implement for locking and unlocking the I2C bus.
*
* \param pi2c The provider I2C interface.
* \param oper The operation to perform (LOCK/UNLOCK)
*
* \return The sfp_status value, one of SFP_STATUS_*
*/
typedef sfp_status_t (*sfp_i2c_mtx_f)(struct sfp_prov_i2c_s * pi2c, sfp_i2c_mtx_op_t oper);
/*!
* Callback to implement for executing a transaction.
*
* \param pi2c The provider I2C interface.
* \param adr The I2C device address, R/w bit set to 0.
* \param trx Transaction object pointer.
*
* \return The sfp_status value, one of SFP_STATUS_*
*/
typedef sfp_status_t (*sfp_i2c_trx_f)(struct sfp_prov_i2c_s * pi2c, uint8_t adr, sfp_i2c_trx_t * trx);
/*!
* Private provided stub.
*/
typedef struct sfp_prov_i2c_s {
sfp_i2c_t pub; //!< Public SFP module structure
sfp_i2c_trx_f trx; //!< I2C transaction
sfp_i2c_mtx_f mtx; //!< I2C mutex
sfp_variant_t user0; //!< User object 0
sfp_variant_t user1; //!< User object 1
} sfp_prov_i2c_t;
#endif /* SFPI2C_PROV_H_ */
/*!
* \file sfpmod.h
*
* \brief User header file for SFP modules.
*
* \author Vincent van Beveren (v.van.beveren[at]nikhef.nl)
* \date 4 July 2017
*/
#ifndef SFPMOD_H_
#define SFPMOD_H_
#include <stdint.h>
#include <stddef.h>
#include "sfpcommon.h"
/*!
* \brief SFP module device.
*/
typedef struct sfp_mod_s {
const char * name;
} sfp_mod_t;
/*!
* \brief Address space of SFP module.
*/
typedef enum sfp_as_e {
AS_A0 = 0xA000, //!< Address space A0, reg range 0-255
AS_A2_LO = 0xA200, //!< Address space A2, reg range 0-127
AS_A2_P0 = 0xA280, //!< Address space A2, page 0, reg range 128-255
AS_A2_P1 = 0xA281, //!< Address space A2, page 1, reg range 128-255
AS_A2_P2 = 0xA282, //!< Address space A2, page 2, reg range 128-255
AS_A2_P3 = 0xA283, //!< Address space A2, page 3, reg range 128-255
AS_A2_P4 = 0xA284, //!< Address space A2, page 4, reg range 128-255
AS_A2_P5 = 0xA285 //!< Address space A2, page 5, reg range 128-255
} sfp_as_t;
/*!
* @{
* \name SFP Flags
* \brief Flags used by \link sfp_mod_status \endlink.
*/
#define SFP_FLAGS_SIG_SUPPORTED 0x01 //!< Signals supported
#define SFP_FLAGS_SIG_TX_FAULT 0x02 //!< TX fault signal is asserted
#define SFP_FLAGS_SIG_RX_LOSS 0x04 //!< RX loss signal is asserted
#define SFP_FLAGS_SIG_MOD_PRESENT 0x08 //!< Module present signal is asserted
/*! @} */
/*!
* \brief Query the number of SFP bays.
*
* The number does not necessary require the module to be actually present. For an 18 port
* switch this number always returns 18. Use the \link SFP_FLAGS_SIG_MOD_PRESENT \endlink signal
* to check if the module is actually in the bay, if supported.
*
* \return The number of possible SFP modules present
*/
SFP_STUB unsigned int sfp_mod_count();
/*!
* \brief Get the reference to a module at the specified index position.
*
* \param idx The index position, 0..sfp_mod_count() - 1 .
* \param module A pointer pointer which will be set to provider module
*
* \return A SFP_STATUS_* value. See \link sfp_status_t \endlink
*/
SFP_STUB sfp_status_t sfp_mod_get(unsigned int idx, sfp_mod_t ** module);
/*!
* \brief Read the SFP eeprom/diagnostics data.
*
* \param mod The module
* \param aspace The address space
* \param reg The register
* \param data The buffer to write the data into
* \paran count The number of bytes to read
*
* \return A SFP_STATUS_* value. See \link sfp_status_t \endlink
*/
sfp_status_t sfp_mod_ee_rd(sfp_mod_t * mod, sfp_as_t aspace, uint8_t reg, uint8_t * data, size_t count);
/*!
* \brief Write the SFP eeprom/diagnostics data.
*
* \param mod The module
* \param aspace The address space
* \param reg The register
* \param data The buffer to read the data from
* \paran count The number of bytes to write
*
* \return A SFP_STATUS_* value. See \link sfp_status_t \endlink
*/
sfp_status_t sfp_mod_ee_wr(sfp_mod_t * mod, sfp_as_t aspace, uint8_t reg, uint8_t * data, size_t count);
/*!
* \brief Get module status flags.
*
* \param mod A pointer to the module
* \param flags A pointer to an integer to get the flags onto.
*
* \return A SFP_STATUS_* value. See \link sfp_status_t \endlink
*/
sfp_status_t sfp_mod_status(sfp_mod_t * mod, uint32_t * flags);
#endif /* SFPMOD_H_ */
/**
* @file
*/
#ifndef SFPMOD_PROV_H_
#define SFPMOD_PROV_H_
#include "sfpmod.h"
#include "sfpi2c.h"
#include "sfpgpio.h"
#include <stdint.h>
#include <stddef.h>
// -----------------------------------------------------------------------------------------------------
// Generic macros
// -----------------------------------------------------------------------------------------------------
// Address space operations
#define SFP_AS2ADDR(AS) ( (AS) >> 8 )
#define SFP_AS_PAGEMASK 0x0080
#define SFP_AS2PAGE(AS) ( (AS) & 0x7F )
// -----------------------------------------------------------------------------------------------------
// Architecture stub functions
// -----------------------------------------------------------------------------------------------------
/**
* Stub functions must be implemented in the architecture code.
*/
sfp_status_t _sfp_mod_get(unsigned int idx, sfp_mod_t ** module);
unsigned int _sfp_mod_count();
// -----------------------------------------------------------------------------------------------------
// High level provider interface.
// -----------------------------------------------------------------------------------------------------
/**
* The high level provider interface is the highest level on which you can implement SFP access functions.
*
*
* There are three main functions to implement:
* ee_rd -> Eeprom read function
* ee_wr -> eeprom write function
* sts -> Module status (usually from GPIO)
*
* Implementation is entirely up to the implementor.
*
* It is also possible to use a ready-made provider, which requires a i2c and gpio abstraction. See
* the composite provider below.
*/
struct sfp_prov_mod_s;
typedef sfp_status_t (*sfp_mod_ee_rd_f)(struct sfp_prov_mod_s * pmod, sfp_as_t aspace, uint8_t reg, uint8_t * data, size_t count);
typedef sfp_status_t (*sfp_mod_ee_wr_f)(struct sfp_prov_mod_s * pmod, sfp_as_t aspace, uint8_t reg, uint8_t * data, size_t count);
typedef sfp_status_t (*sfp_mod_sts_f )(struct sfp_prov_mod_s * pmod, uint32_t * flags);
/**
* Provider interface.
*/
typedef struct sfp_prov_mod_s {
sfp_mod_t pub; //!< Public SFP module structure
sfp_mod_ee_rd_f ee_rd; //!< Eeprom read
sfp_mod_ee_wr_f ee_wr; //!< Eeprom write
sfp_mod_sts_f sts; //!< Get status
sfp_variant_t user; //!< Custom data object.
} sfp_prov_mod_t;
// -----------------------------------------------------------------------------------------------------
// Composite provider interface
// -----------------------------------------------------------------------------------------------------
#define SFP_MUX_TYP_NONE 0x00 //!< There is no mux
#define SFP_MUX_TYP_I2C 0x01 //!< Its a I2C mux
#define SFP_MUX_PART_PCA9548 0x01 //!< PCA9548 I2C mux
/*!
* Mux definition union.
*
* Type defines the argument. If type is I2C, then the i2c union should be used.
*
* Currently only the PCA9548 is supported, but I'm pretty sure there are many alike.
*/
typedef union sfp_mux_op {
struct {
uint8_t typ;
uint8_t __resv[3];
} any;
struct {
uint8_t typ;
uint8_t part;
uint8_t addr;
uint8_t pos;
} i2c;
// optional other mux types (GPIO?)
uint32_t val; // for simple 0 assignment
} sfp_mux_op_t;
/*!
* Composite SFP MOD structure.
*
* When accessing an EEPROM register, the following sequence is executed:
*
* 1) The I2C mutex lock function is called
* 2) The first and second mux operation are executed, if set
* 3) The i2c read/write operation is executed in the provider register
* 4) The I2C mutex is released
*/
typedef struct sfp_comp_mod_s {
sfp_prov_mod_t prov; //!< Provider interface
sfp_i2c_t * i2c; //!< I2C bus pointer
sfp_mux_op_t mux0; //!< Mux level 0, if any
sfp_mux_op_t mux1; //!< Mux level 1, if any
sfp_gpio_pin_t tx_fault; //!< Tx fault GPIO, or SFP_GPIO_NONE
sfp_gpio_pin_t rx_loss; //!< Rx loss GPIO, or SFP_GPIO_NONE
sfp_gpio_pin_t mod_prsnt; //!< Module present GPIO, or SFP_GPIO_NONE
sfp_gpio_pin_t reserved; //!< Reserved
} sfp_comp_mod_t;
sfp_status_t sfp_comp_mod_ee_rd(struct sfp_prov_mod_s * pmod, sfp_as_t aspace, uint8_t reg, uint8_t * data, size_t count);
sfp_status_t sfp_comp_mod_ee_wr(struct sfp_prov_mod_s * pmod, sfp_as_t aspace, uint8_t reg, uint8_t * data, size_t count);
sfp_status_t sfp_comp_mod_sts (struct sfp_prov_mod_s * pmod, uint32_t * flags);
#endif /* SFPMOD_PROV_H_ */
/*
* sfpi2c.c
*
* Created on: 4 jul. 2017
* Author: vincentb
*/
#include "sfpi2c_prov.h"
sfp_status_t sfp_i2c_trx(sfp_i2c_slave_t * slave, sfp_i2c_trx_t * trx)
{
sfp_prov_i2c_t * pi2c = (sfp_prov_i2c_t *)slave->i2c;
return pi2c->trx(pi2c, slave->addr, trx);
}
sfp_status_t sfp_i2c_mtx(sfp_i2c_t * i2c, sfp_i2c_mtx_op_t oper)
{
sfp_prov_i2c_t * pi2c = (sfp_prov_i2c_t *)i2c;
return pi2c->mtx(pi2c, oper);
}
/*
* sfpmod.c
*
* Created on: 26 jun. 2017
* Author: vincentb
*/
#include "sfpmod.h"
#include <stdbool.h>
#include "sfpmod_prov.h"
#define SFP_REG_PAGE 127
sfp_status_t sfp_mod_get(unsigned int idx, sfp_mod_t ** module)
{
return _sfp_mod_get(idx, module);
}
unsigned int sfp_mod_count()
{
return _sfp_mod_count();
}
sfp_status_t sfp_mod_ee_rd(sfp_mod_t * mod, sfp_as_t aspace, uint8_t reg, uint8_t * data, size_t count)
{
sfp_prov_mod_t * pmod = (sfp_prov_mod_t *)mod;
return pmod->ee_rd(pmod, aspace, data, reg, count);
}
sfp_status_t sfp_mod_ee_wr(sfp_mod_t * mod, sfp_as_t aspace, uint8_t reg, uint8_t * data, size_t count)
{
sfp_prov_mod_t * pmod = (sfp_prov_mod_t *)mod;
return pmod->ee_wr(pmod, aspace, data, reg, count);
}
sfp_status_t sfp_mod_status(sfp_mod_t * mod, uint32_t * flags)
{
sfp_prov_mod_t * pmod = (sfp_prov_mod_t *)mod;
return pmod->sts(pmod, flags);
}
// -----------------------------------------------------------------------------------------------------
// Composite provider interface
// -----------------------------------------------------------------------------------------------------
sfp_status_t sfp_comp_mod_set_mux(sfp_comp_mod_t * cmod, sfp_mux_op_t * op)
{
uint8_t t;
sfp_i2c_slave_t slave;
switch (op->any.typ)
{
case SFP_MUX_TYP_I2C:
// I2C Mux switch
switch (op->i2c.part)
{
case SFP_MUX_PART_PCA9548:
// set the I2C mux to the right position
t = 1 << op->i2c.pos;
slave = sfp_i2c_slave(cmod->i2c, op->i2c.addr);
return sfp_i2c_wr(&slave, &t, 1);
default:
break;
}
/* no break */
default:
return SFP_STATUS_MODULE_CONFIG_ERROR;
}
return SFP_STATUS_OK;
}
sfp_status_t sfp_comp_mod_set_muxes(sfp_comp_mod_t * cmod)
{
sfp_status_t sts = SFP_STATUS_OK;
if (cmod->mux0.val != 0)
{
sts = sfp_comp_mod_set_mux(cmod, &cmod->mux0);
if (sts != SFP_STATUS_OK) return sts;
}
if (cmod->mux1.val != 0) sts = sfp_comp_mod_set_mux(cmod, &cmod->mux1);
return sts;
}
sfp_status_t sfp_comp_mod_ee_rd(struct sfp_prov_mod_s * pmod, sfp_as_t aspace, uint8_t reg, uint8_t * data, size_t count)
{
sfp_comp_mod_t * cmod = (sfp_comp_mod_t *)pmod;
sfp_status_t sts = sfp_i2c_mtx(cmod->i2c, SFP_I2C_MUX_LOCK);
if (sts != SFP_STATUS_OK) return sts;
sts = sfp_comp_mod_set_muxes(cmod);
if (sts != SFP_STATUS_OK) goto finally;
// get slave instance.
sfp_i2c_slave_t slave = sfp_i2c_slave(cmod->i2c, SFP_AS2ADDR(aspace));
// if these is a page mask, set it
if (aspace & SFP_AS_PAGEMASK)
{
uint8_t page = SFP_AS2PAGE(aspace);
sts = sfp_i2c_a8_wr(&slave, SFP_REG_PAGE, &page, 1);
if (sts != SFP_STATUS_OK) goto finally;
}
sts = sfp_i2c_a8_rd(&slave, reg, data, count);
finally:
sfp_i2c_mtx(cmod->i2c, SFP_I2C_MUX_UNLOCK);
return sts;
}
#ifdef SFP_WRITE_SUPPORT
sfp_status_t sfp_comp_mod_ee_wr(struct sfp_prov_mod_s * pmod, sfp_as_t aspace, uint8_t reg, uint8_t * data, size_t count)
{
sfp_comp_mod_t * cmod = (sfp_comp_mod_t *)pmod;
sfp_status_t sts = sfp_i2c_mtx(cmod->i2c, SFP_I2C_MUX_LOCK);
if (sts != SFP_STATUS_OK) return sts;
sts = sfp_comp_mod_set_muxes(cmod);
if (sts != SFP_STATUS_OK) goto finally;
sfp_i2c_slave_t slave = sfp_i2c_slave(cmod->i2c, SFP_AS2ADDR(aspace));
// if these is a page mask, set it
if (aspace & SFP_AS_PAGEMASK)
{
uint8_t page = SFP_AS2PAGE(aspace);
sts = sfp_i2c_a8_wr(&slave, SFP_REG_PAGE, &page, 1);
if (sts != SFP_STATUS_OK) goto finally;
}
if (reg % 8 == 0 && count == 8)
{
// simple case, write one register with offset of 8 and with 8 bytes
sts = sfp_i2c_a8_wr(&slave, reg, data, count);
} else {
// complex writing is not supported yet
return SFP_STATUS_NOT_SUPPORTED;
}
finally:
sfp_i2c_mtx(cmod->i2c, SFP_I2C_MUX_UNLOCK);
return sts;
}
#else
sfp_status_t sfp_comp_mod_ee_wr(struct sfp_prov_mod_s * pmod, sfp_as_t aspace, uint8_t reg, uint8_t * data, size_t count)
{
return SFP_STATUS_NOT_SUPPORTED;
}
#endif
sfp_status_t sfp_comp_mod_sts (struct sfp_prov_mod_s * pmod, uint32_t * flags)
{
sfp_comp_mod_t * cmod = (sfp_comp_mod_t *)pmod;
uint32_t flags_;
// If all GPIOs are defined
if (cmod->rx_loss != SFP_GPIO_NONE && cmod->tx_fault != SFP_GPIO_NONE && cmod->mod_prsnt != SFP_GPIO_NONE)
{
// We assume we can use it.
flags_ = SFP_FLAGS_SIG_SUPPORTED;
if (gpio_get_level(cmod->rx_loss)) flags_ |= SFP_FLAGS_SIG_RX_LOSS;
if (gpio_get_level(cmod->tx_fault)) flags_ |= SFP_FLAGS_SIG_TX_FAULT;
if (gpio_get_level(cmod->mod_prsnt)) flags_ |= SFP_FLAGS_SIG_MOD_PRESENT;
} else {
// Otherwise, not.
flags_ = 0;
}
*flags = flags_;
return SFP_STATUS_OK;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment