From 4a0eb4f2b0945ccfebba006292dd2456cd4f4a48 Mon Sep 17 00:00:00 2001 From: WeebDataHoarder <57538841+WeebDataHoarder@users.noreply.github.com> Date: Sun, 24 Oct 2021 21:32:49 +0200 Subject: [PATCH] Working example --- .gitignore | 1 + CMakeLists.txt | 6 +- build.sh | 14 +++ src/FM10K.h | 25 ---- src/device/Device.h | 10 +- src/device/PCIEDevice.cpp | 214 ++++++++++++++++++++++++--------- src/device/PCIEDevice.h | 66 ++++++++-- src/fm10k/Constants.h | 12 ++ src/{ => fm10k}/FM10K.cpp | 0 src/fm10k/FM10K.h | 57 +++++++++ src/fm10k/Functions.cpp | 2 + src/fm10k/Functions.h | 20 +++ src/fm10k/registers/MGMT.h | 50 ++++++++ src/fm10k/registers/Register.h | 11 ++ src/fsmd.cpp | 36 ++++-- src/pack.h | 46 +++++++ src/registers/MGMT.h | 8 -- src/registers/pack.h | 23 ---- test/test-gcc-struct.cpp | 28 +++++ 19 files changed, 494 insertions(+), 135 deletions(-) create mode 100755 build.sh delete mode 100644 src/FM10K.h create mode 100644 src/fm10k/Constants.h rename src/{ => fm10k}/FM10K.cpp (100%) create mode 100644 src/fm10k/FM10K.h create mode 100644 src/fm10k/Functions.cpp create mode 100644 src/fm10k/Functions.h create mode 100644 src/fm10k/registers/MGMT.h create mode 100644 src/fm10k/registers/Register.h create mode 100644 src/pack.h delete mode 100644 src/registers/MGMT.h delete mode 100644 src/registers/pack.h create mode 100644 test/test-gcc-struct.cpp diff --git a/.gitignore b/.gitignore index eda6344..10a786d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /cmake-build-debug +/build .idea \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ef27c8..e2df2d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,9 @@ cmake_minimum_required(VERSION 3.13) -project(src) +project(fsm) set(CMAKE_CXX_STANDARD 14) -add_executable(fsmd src/fsmd.cpp src/device/PCIEDevice.cpp src/device/PCIEDevice.h src/FM10K.cpp src/FM10K.h) +include_directories(${fsm_SOURCE_DIR}/src) + +add_executable(fsmd src/fsmd.cpp src/device/PCIEDevice.cpp src/device/PCIEDevice.h src/fm10k/FM10K.cpp src/fm10k/FM10K.h src/fm10k/Functions.h src/fm10k/Functions.cpp) add_executable(fsm src/fsm.cpp) diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..431804a --- /dev/null +++ b/build.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -ex + +pushd "${0%/*}" +rm -rvf build +mkdir build +pushd build + +export CC=clang +export CXX=clang++ +export CFLAGS="-ggdb -O0 -march=x86-64 -mtune=generic" +export CXXFLAGS="-ggdb -O0 -march=x86-64 -mtune=generic" +cmake .. +make -j$(nproc) \ No newline at end of file diff --git a/src/FM10K.h b/src/FM10K.h deleted file mode 100644 index 47832e8..0000000 --- a/src/FM10K.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - - -#include -#include -#include -#include "device/Device.h" -#include "registers/MGMT.h" - -class FM10K { -public: - static const uint64_t BAR4_SIZE = 0x0000000004000000; - static const uint64_t BAR4_OFFSET = 0x0; - - explicit FM10K(std::unique_ptr device) : m_device(std::move(device)) { - - } - - - -private: - std::unique_ptr m_device; -}; - - diff --git a/src/device/Device.h b/src/device/Device.h index 3e73d71..a780e76 100644 --- a/src/device/Device.h +++ b/src/device/Device.h @@ -5,9 +5,11 @@ public: virtual ~Device()= default; virtual bool valid() const = 0; - virtual uint32_t get32(uint64_t address) const = 0; - virtual void set32(uint64_t address, uint32_t value) const = 0; + virtual uint32_t get32(uint32_t address) const = 0; + virtual void set32(uint32_t address, uint32_t value) const = 0; - virtual uint64_t get64(uint64_t address) const = 0; - virtual void set64(uint64_t address, uint64_t value) const = 0; + virtual volatile uint32_t* map32(uint32_t address) const = 0; + + virtual uint64_t get64(uint32_t address) const = 0; + virtual void set64(uint32_t address, uint64_t value) const = 0; }; \ No newline at end of file diff --git a/src/device/PCIEDevice.cpp b/src/device/PCIEDevice.cpp index 19661fc..1d8d4f1 100644 --- a/src/device/PCIEDevice.cpp +++ b/src/device/PCIEDevice.cpp @@ -3,8 +3,48 @@ #include #include #include +#include +#include #include "PCIEDevice.h" -#include "../FM10K.h" +#include "fm10k/FM10K.h" + +std::vector get_file_contents(const std::string& path){ + std::ifstream file; + file.open(path, std::ios::in | std::ios::binary); + if(file.fail()){ + file.close(); + return {}; + } + + std::vector data; + + std::for_each(std::istreambuf_iterator(file), + std::istreambuf_iterator(), + [&data](const char c){ + data.push_back(c); + }); + + file.close(); + return std::move(data); +} + +uint64_t get_file_integer(const std::string& path){ + auto s = get_file_contents(path); + std::string t; + t.reserve(s.empty() ? 0 : s.size() - 1); + + for(auto& c : s){ + if(c == '\n'){ + break; + } + t += c; + } + + if(t.empty()){ + return -1; + } + return std::strtoul(t.c_str(), nullptr, 0); +} std::vector PCIEDevice::DeviceEntry::find() { std::vector entries; @@ -20,73 +60,42 @@ std::vector PCIEDevice::DeviceEntry::find() { struct dirent *entry; - std::string fileName; - while ((entry = readdir(folder))) { + std::string basePath("/sys/bus/pci/devices/"); + basePath += entry->d_name; + if (entry->d_type == DT_DIR || entry->d_type == DT_LNK) { - fileName = "/sys/bus/pci/devices/"; - fileName += entry->d_name; - fileName += "/vendor"; - FILE *vendorBytesPointer = fopen(fileName.c_str(), "rb"); - if (vendorBytesPointer != nullptr) { - char *vendorBytesBuffer = nullptr; - size_t vendorBytesLen; - size_t vendorBytesRead = getdelim(&vendorBytesBuffer, &vendorBytesLen, '\0', vendorBytesPointer); - if (vendorBytesRead != -1) { - int vendor = (int) strtol(vendorBytesBuffer, nullptr, 0); + uint16_t vendor = get_file_integer(basePath + "/vendor"); + uint16_t _class = get_file_integer(basePath + "/device"); - if (vendor == 0x8086) { //Intel Corporation + if ( + vendor == 0x8086 //Intel Corporation + && + (_class == 0x15a4 || _class == 0x15d0 || _class == 0x15d5) //FM10000 devices + ) { + if (access((basePath + "/resource4").c_str(), F_OK) == 0) { - fileName = "/sys/bus/pci/devices/"; - fileName += entry->d_name; - fileName += "/device"; - FILE *classBytesPointer = fopen(fileName.c_str(), "rb"); - if (classBytesPointer != nullptr) { - char *classBytesBuffer = nullptr; - size_t classBytesLen; - size_t classBytesRead = getdelim(&classBytesBuffer, &classBytesLen, '\0', - classBytesPointer); - if (classBytesRead != -1) { - int _class = (int) strtol(classBytesBuffer, nullptr, 0); - - if (_class == 0x15a4 || _class == 0x15d0 || _class == 0x15d5) { //FM10000 devices - fileName = "/sys/bus/pci/devices/"; - fileName += entry->d_name; - fileName += "/resource4"; - if (access(fileName.c_str(), F_OK) == 0) { - entries.emplace_back(fileName, vendor, _class); - } - } - } - - if (classBytesBuffer != nullptr) { - free(classBytesBuffer); - } - fclose(classBytesPointer); - } - } + auto vpd = get_file_contents(basePath + "/vpd"); + entries.emplace_back(basePath + "/resource4", vendor, _class, vpd); } - - if (vendorBytesBuffer != nullptr) { - free(vendorBytesBuffer); - } - fclose(vendorBytesPointer); } } } + closedir(folder); + return entries; } -PCIEDevice::PCIEDevice(PCIEDevice::DeviceEntry device) : m_device (std::move(device)){ +PCIEDevice::PCIEDevice(const PCIEDevice::DeviceEntry& device) : m_device (device){ m_bar4Resource = open(m_device.getPath().c_str(), O_RDWR); if(m_bar4Resource <= 0){ //TODO printf("Unable to open BAR4 resource %s\n", m_device.getPath().c_str()); return; } - m_bar4mmap = mmap(nullptr, FM10K::BAR4_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, m_bar4Resource, 0); + m_bar4mmap = static_cast(mmap(nullptr, FM10K::BAR4_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, m_bar4Resource, 0)); if(m_bar4mmap == MAP_FAILED){ //TODO printf("Unable to map BAR4 resource %s\n", m_device.getPath().c_str()); close(m_bar4Resource); @@ -110,18 +119,109 @@ PCIEDevice::~PCIEDevice() { } } -uint32_t PCIEDevice::get32(uint64_t address) const { - return *(((volatile uintptr_t *) m_bar4mmap) + address); +uint32_t PCIEDevice::get32(uint32_t address) const { + return (m_bar4mmap && address < FM10K::BAR4_SIZE) ? *getaddress(address) : 0; } -void PCIEDevice::set32(uint64_t address, uint32_t value) const { - *(volatile uintptr_t *) (((uintptr_t *) m_bar4mmap) + address) = value; +void PCIEDevice::set32(uint32_t address, uint32_t value) const { + if(m_bar4mmap && address < FM10K::BAR4_SIZE){ + *getaddress(address) = value; + } } -uint64_t PCIEDevice::get64(uint64_t address) const { - return *(((volatile uintptr_t *) m_bar4mmap) + address); +uint64_t PCIEDevice::get64(uint32_t address) const { + return (m_bar4mmap && (address + 1) < FM10K::BAR4_SIZE) ? *reinterpret_cast(getaddress(address)) : 0; } -void PCIEDevice::set64(uint64_t address, uint64_t value) const { - *(uintptr_t volatile *) (((uintptr_t *) m_bar4mmap) + address) = value; +void PCIEDevice::set64(uint32_t address, uint64_t value) const { + if(m_bar4mmap && (address + 1) < FM10K::BAR4_SIZE){ + *reinterpret_cast(getaddress(address)) = value; + } +} + +volatile uint32_t* PCIEDevice::map32(uint32_t address) const { + return (m_bar4mmap && address < FM10K::BAR4_SIZE) ? getaddress(address) : nullptr; +} + +PCIEDevice::VitalProductData::VitalProductData(const std::vector& s) { + size_t offset = 0; + + while(offset < s.size()){ + ResourceType t(s, offset); + + + switch (t.getName()) { + + case ResourceType::TypeName::StringTag: + if(m_vpd.empty()){ + //Product Name + m_vpd.emplace("Product Name", t.getData()); + } + break; + case ResourceType::TypeName::VPD_R: + { + size_t o = 0; + while (o < t.getData().size()){ + fillFromEntry(t.getData(), o); + } + } + break; + case ResourceType::TypeName::VPD_W: + { + size_t o = 0; + while (o < t.getData().size()){ + fillFromEntry(t.getData(), o); + } + } + break; + case ResourceType::TypeName::End: + return; + } + }; +} + +void PCIEDevice::VitalProductData::fillFromEntry(const std::vector &v, size_t& offset) { + std::string keyword; + keyword.reserve(2); + + keyword += static_cast(v[offset++]); + keyword += static_cast(v[offset++]); + uint8_t length = v[offset++]; + + std::vector data; + std::copy(v.begin() + offset, v.begin() + offset + length, std::back_inserter(data)); + offset += length; + + m_vpd.emplace(std::move(keyword), std::move(data)); +} + +PCIEDevice::VitalProductData::ResourceType::ResourceType(const std::vector& s, size_t& offset) { + uint8_t h = s[offset++]; + + uint16_t length = 0; + + if(((h>>7)&1) == 0){ //Small Data Type + PACKED(struct { + uint8_t length : 3; + uint8_t name : 4; + uint8_t type : 1; + }, uint8_t) header{}; + header.value = h; + + m_name = static_cast(header.fields.name); + length = header.fields.length; + }else{ //Large Data Type + PACKED(struct { + uint8_t name : 7; + uint8_t type : 1; + }, uint8_t) header{}; + header.value = h; + + m_name = static_cast(header.fields.name); + length = s[offset] | s[offset + 1] << 8; + offset += 2; + } + + std::copy(s.begin() + offset, s.begin() + offset + length, std::back_inserter(m_data)); + offset += length; } diff --git a/src/device/PCIEDevice.h b/src/device/PCIEDevice.h index 9475c9a..8a11d90 100644 --- a/src/device/PCIEDevice.h +++ b/src/device/PCIEDevice.h @@ -2,24 +2,66 @@ #include #include +#include +#include #include "Device.h" class PCIEDevice: public Device { public: + class VitalProductData{ + public: + class ResourceType { + public: + enum class TypeName : uint8_t{ + StringTag = 0x02, + VPD_R = 0x10, + VPD_W = 0x11, + End = 0x0f, + }; + + explicit ResourceType(const std::vector& s, size_t& offset); + + TypeName getName() const{ + return m_name; + } + + const auto& getData() const{ + return m_data; + } + + protected: + TypeName m_name; + std::vector m_data; + }; + + explicit VitalProductData(const std::vector& s); + + private: + void fillFromEntry(const std::vector& v, size_t& offset); + + std::unordered_map> m_vpd; + }; + class DeviceEntry{ public: - DeviceEntry(std::string path, uint16_t vendor, uint16_t _class) : m_path(std::move(path)), m_class(_class), m_vendor(vendor){ + DeviceEntry(std::string path, uint16_t vendor, uint16_t _class, const std::vector& vpd) : m_path(std::move(path)), m_class(_class), m_vendor(vendor), m_vpd(vpd){ } + DeviceEntry(const DeviceEntry& a) =default; + static std::vector find(); - const std::string& getPath() const{ + const auto& getPath() const{ return m_path; } + const auto& getVPD() const{ + return m_vpd; + } + uint16_t getVendor() const{ return m_vendor; } @@ -31,15 +73,17 @@ public: std::string m_path; uint16_t m_vendor; uint16_t m_class; + VitalProductData m_vpd; }; - explicit PCIEDevice(PCIEDevice::DeviceEntry device); + explicit PCIEDevice(const PCIEDevice::DeviceEntry& device); - uint32_t get32(uint64_t address) const override; - void set32(uint64_t address, uint32_t value) const override; + uint32_t get32(uint32_t address) const override; + volatile uint32_t* map32(uint32_t address) const override; + void set32(uint32_t address, uint32_t value) const override; - uint64_t get64(uint64_t address) const override; - void set64(uint64_t address, uint64_t value) const override; + uint64_t get64(uint32_t address) const override; + void set64(uint32_t address, uint64_t value) const override; const PCIEDevice::DeviceEntry& getDeviceEntry() const{ return m_device; @@ -49,11 +93,15 @@ public: return m_bar4mmap != nullptr && m_bar4Resource > 0; } - ~PCIEDevice(); + ~PCIEDevice() override; + private: + volatile uint32_t* getaddress(uint32_t address) const { + return m_bar4mmap + address; + } int m_bar4Resource = 0; - void* m_bar4mmap = nullptr; + uint32_t* m_bar4mmap = nullptr; PCIEDevice::DeviceEntry m_device; }; diff --git a/src/fm10k/Constants.h b/src/fm10k/Constants.h new file mode 100644 index 0000000..7f512a8 --- /dev/null +++ b/src/fm10k/Constants.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Functions.h" + +namespace FM10K { + const uint64_t BAR4_SIZE = 0x0000000004000000; + const uint64_t BAR4_OFFSET = 0x0; + + //These should not be set (on hw) to more than 1100 or less than 800 + constexpr uint32_t DEFAULT_VDDS_VOLTAGE = 850; //Spec says 0.9 Volts, and also 0.85 + constexpr uint32_t DEFAULT_VDDF_VOLTAGE = 950; //Spec says 0.9 Volts, and also 0.95 +} \ No newline at end of file diff --git a/src/FM10K.cpp b/src/fm10k/FM10K.cpp similarity index 100% rename from src/FM10K.cpp rename to src/fm10k/FM10K.cpp diff --git a/src/fm10k/FM10K.h b/src/fm10k/FM10K.h new file mode 100644 index 0000000..a1f2c9a --- /dev/null +++ b/src/fm10k/FM10K.h @@ -0,0 +1,57 @@ +#pragma once + + +#include +#include +#include +#include +#include "device/Device.h" +#include "registers/MGMT.h" +#include "Constants.h" + +#define FM10K_GET_REGISTER(i, t) i.getType(t ## __Address) +#define FM10K_MAP_REGISTER(i, t) i.mapType(t ## __Address) +#define FM10K_SET_REGISTER(i, t, v) i.setType(t ## __Address, v) +#define FM10K_SET_REGISTER_FIELD(i, t, f, v) \ +auto __f = FM10K_MAP_REGISTER(i, t); \ +__f->fields. f = v + +namespace FM10K{ + + class FM10K { + public: + + explicit FM10K(std::unique_ptr device) : m_device(std::move(device)) { + + } + + template volatile T* mapType(uint32_t address) const { + return reinterpret_cast(m_device->map32(address)); + } + + template T getType(uint32_t address) const { + T t; + t.value = m_device->get32(address); + return std::move(t); + } + + template void setType(uint32_t address, const T& t) const { + t.value = m_device->set32(address, t.value); + return std::move(t); + } + + template void setTypeMask(uint32_t address, uint32_t mask, const T& t) const { + t.value = m_device->set32(address, t.value & mask); + return std::move(t); + } + + + + private: + std::unique_ptr m_device; + }; + +} + + + diff --git a/src/fm10k/Functions.cpp b/src/fm10k/Functions.cpp new file mode 100644 index 0000000..e256a83 --- /dev/null +++ b/src/fm10k/Functions.cpp @@ -0,0 +1,2 @@ +#include "Functions.h" + diff --git a/src/fm10k/Functions.h b/src/fm10k/Functions.h new file mode 100644 index 0000000..f5364cf --- /dev/null +++ b/src/fm10k/Functions.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +namespace FM10K{ + + constexpr uint32_t VR12_VID_to_Millivolts(uint8_t v){ + return v == 0 ? 0 : 5 * (v - 1) + 250; + } + + constexpr uint32_t Volts_to_Millivolts(double v){ + return static_cast(v * 1000.0); + } + + constexpr uint8_t Millivolts_to_VR12_VID(uint32_t v){ + return ((v - 250) / 5) + 1; + } + +} \ No newline at end of file diff --git a/src/fm10k/registers/MGMT.h b/src/fm10k/registers/MGMT.h new file mode 100644 index 0000000..66fa62a --- /dev/null +++ b/src/fm10k/registers/MGMT.h @@ -0,0 +1,50 @@ +#pragma once + +#include "Register.h" + +namespace FM10K{ + namespace registers{ + namespace MGMT{ + enum class DEVICE_CFG_FeatureCode: uint8_t { + FULL = 0b00, + HALF = 0b01, + BASIC = 0b10, + RESERVED = 0b11, + }; + + typedef PACKED(struct { + uint8_t PCIeMode: 4; //Bitfield array [0..3] + uint8_t Eth100GDisabled: 1; + DEVICE_CFG_FeatureCode FeatureCode: 2; + uint16_t PCIeEnable: 9; //Bitfield array [0..8] + uint8_t SystimeClockSource: 1; + uint16_t : 15; + }, uint32_t) DEVICE_CFG; + const uint32_t DEVICE_CFG__Address = 0x4; + + + typedef PACKED(struct { + uint16_t PartNumber : 16; + uint16_t : 16; + }, uint32_t) VITAL_PRODUCT_DATA; + const uint32_t VITAL_PRODUCT_DATA__Address = 0x304; + + typedef PACKED(struct { + uint16_t ChipVersion : 7; + uint32_t : 25; + }, uint32_t) CHIP_VERSION; + const uint32_t CHIP_VERSION__Address = 0x452; + + typedef PACKED(struct { + uint16_t : 11; + uint8_t SKU : 5; + uint8_t VDDS_VRM : 8; + uint8_t VDDF_VRM : 8; + }, uint32_t) FUSE_DATA_0; + const uint32_t FUSE_DATA_0__Address = 0xC0E; + + } + } +} + + diff --git a/src/fm10k/registers/Register.h b/src/fm10k/registers/Register.h new file mode 100644 index 0000000..dcf3b77 --- /dev/null +++ b/src/fm10k/registers/Register.h @@ -0,0 +1,11 @@ +#pragma once + +#include "pack.h" +#include "MGMT.h" + +namespace FM10K{ + namespace registers{ + + + } +} diff --git a/src/fsmd.cpp b/src/fsmd.cpp index a68e7ee..6ddf501 100644 --- a/src/fsmd.cpp +++ b/src/fsmd.cpp @@ -1,6 +1,17 @@ #include #include +#include +#include #include "device/PCIEDevice.h" +#include "fm10k/FM10K.h" +#include "fm10k/registers/Register.h" + +template std::string tohex(T v){ + std::stringstream o; + o << std::hex << std::setw(sizeof(v) * 2) << std::setfill('0') << v; + + return o.str(); +} int main() { auto entries = PCIEDevice::DeviceEntry::find(); @@ -8,13 +19,24 @@ int main() { std::cout << "Found " << entries.size() << " FM10K management device(s)." << std::endl; for(auto& entry : entries){ - auto dev = std::make_unique(entry); - std::cout << "dev.path: " << dev->getDeviceEntry().getPath() << std::endl; - std::cout << "dev.vendor: " << dev->getDeviceEntry().getVendor() << std::endl; - std::cout << "dev.class: " << dev->getDeviceEntry().getClass() << std::endl; - std::cout << "DEVICE_CFG: " << dev->get32(0x4) << std::endl; - std::cout << "BSM_ARGS: " << dev->get32(0xC00) << std::endl; - std::cout << "FUSE_DATA(64): " << dev->get64(0xC0E) << std::endl; + auto dev = std::make_unique(entry); + + std::cout << "dev.path: " << dev->getDeviceEntry().getPath() << std::endl; + std::cout << "dev.vendor: " << tohex(dev->getDeviceEntry().getVendor()) << std::endl; + std::cout << "dev.class: " << tohex(dev->getDeviceEntry().getClass()) << std::endl; + + FM10K::FM10K fm10k(std::move(dev)); + + auto fuseData_0 = FM10K_MAP_REGISTER(fm10k, FM10K::registers::MGMT::FUSE_DATA_0); + std::cout << "FUSE_DATA_0: " << tohex(fuseData_0->value) << std::endl; + std::cout << "FUSE_DATA_0.SKU: " << std::to_string(fuseData_0->fields.SKU) << std::endl; + std::cout << "FUSE_DATA_0.VDDF_VRM: " << std::to_string(fuseData_0->fields.VDDS_VRM) << std::endl; + std::cout << "FUSE_DATA_0.VDDF_VRM: " << std::to_string(fuseData_0->fields.VDDF_VRM) << std::endl; + + auto deviceCfg = FM10K_MAP_REGISTER(fm10k, FM10K::registers::MGMT::DEVICE_CFG); + std::cout << "DEVICE_CFG: " << tohex(deviceCfg->value) << std::endl; + auto vpd = FM10K_MAP_REGISTER(fm10k, FM10K::registers::MGMT::VITAL_PRODUCT_DATA); + std::cout << "VITAL_PRODUCT_DATA.PartNumber: " << tohex(vpd->fields.PartNumber) << std::endl; } return 0; } diff --git a/src/pack.h b/src/pack.h new file mode 100644 index 0000000..0a4146d --- /dev/null +++ b/src/pack.h @@ -0,0 +1,46 @@ +#pragma once +#include + +#if defined(__GNUC__) && !defined(__clang__) +#error "GCC is currently not supported due to volatile union packed struct issue. Use clang instead" +#endif + +#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 4)) || defined(__clang__) || defined(__TINYC__) + +#if defined(__TINYC__) + +#define PACKED(x, s) \ +_Pragma("pack(1)") \ +union { \ + s value; \ + x __attribute__((packed)) fields; \ +} \ +_Pragma("pack(1)") + +#define PACKEDM(x, s, n) \ +_Pragma("pack(1)") \ +union { \ + s value[n]; \ + x __attribute__((packed)) fields; \ +} \ +_Pragma("pack(1)") + +#else + +#define PACKED(x, s) \ +union { \ + s value; \ + x __attribute__((packed, aligned(sizeof(s)))) fields; \ + } __attribute__((packed, aligned(sizeof(s)))) + +#define PACKEDM(x, s, n) \ +union { \ + s value[n]; \ + x __attribute__((packed, aligned(sizeof(s)))) fields; \ + } __attribute__((packed, aligned(sizeof(s)))) + +#endif + +#else +#error "Packed bit-fields of type char were not properly bit-packed on many targets prior to GCC 4.4, upgrade to GCC >= 4.4." +#endif \ No newline at end of file diff --git a/src/registers/MGMT.h b/src/registers/MGMT.h deleted file mode 100644 index dbb33e4..0000000 --- a/src/registers/MGMT.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "pack.h" - -namespace MGMT{ - -} - diff --git a/src/registers/pack.h b/src/registers/pack.h deleted file mode 100644 index 260d7c4..0000000 --- a/src/registers/pack.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include "stdint.h" - -#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 4)) || __clang__ || __TINYC__ - -#if defined(__TINYC__) -#pragma pack(1) -#endif - - -#define PACKED(x, s) union { \ - s value; \ - x __attribute__((packed)) fields; \ -} - -#define PACKEDM(x, s, n) union { \ - s value[n]; \ - x __attribute__((packed)) fields; \ -} - -#else -#error "Packed bit-fields of type char were not properly bit-packed on many targets prior to GCC 4.4, upgrade to GCC >= 4.4." -#endif \ No newline at end of file diff --git a/test/test-gcc-struct.cpp b/test/test-gcc-struct.cpp new file mode 100644 index 0000000..cb63f43 --- /dev/null +++ b/test/test-gcc-struct.cpp @@ -0,0 +1,28 @@ +#include +#include + +#define PACKED(x, s) \ +union { \ +s value; \ +x __attribute__((packed, aligned(sizeof(s)))) fields; \ +} __attribute__((packed, aligned(sizeof(s)))) + +typedef PACKED(struct { + uint16_t PartNumber : 16; + uint16_t _reserved: 16; + }, uint32_t) VITAL_PRODUCT_DATA; + +static volatile uint32_t v = 0x0000ae21; +static volatile uint32_t* vpd = &v; + +template volatile T* mapType() { + return reinterpret_cast(vpd); +} + +int main(){ + auto tt = mapType(); + uint16_t t = tt->fields.PartNumber; + + printf("%d\n", tt->value); + printf("%d\n", t); +} \ No newline at end of file