diff --git a/CM4/.settings/language.settings.xml b/CM4/.settings/language.settings.xml index 2c6de0e..43ab036 100644 --- a/CM4/.settings/language.settings.xml +++ b/CM4/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -16,7 +16,7 @@ - + diff --git a/CM4/Core/Src/main.c b/CM4/Core/Src/main.c index 4249f00..f3901e8 100644 --- a/CM4/Core/Src/main.c +++ b/CM4/Core/Src/main.c @@ -169,8 +169,8 @@ void MX_QUADSPI_Init(void) hqspi.Init.ClockPrescaler = 255; hqspi.Init.FifoThreshold = 1; hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE; - hqspi.Init.FlashSize = 1; - hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE; + hqspi.Init.FlashSize = 26; + hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_2_CYCLE; hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0; hqspi.Init.FlashID = QSPI_FLASH_ID_1; hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE; diff --git a/CM7/.cproject b/CM7/.cproject index 1f428bd..16ba8c9 100644 --- a/CM7/.cproject +++ b/CM7/.cproject @@ -146,9 +146,9 @@ - + @@ -295,9 +295,9 @@ - + diff --git a/CM7/.settings/language.settings.xml b/CM7/.settings/language.settings.xml index c9ad366..ef00650 100644 --- a/CM7/.settings/language.settings.xml +++ b/CM7/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -16,7 +16,7 @@ - + diff --git a/CM7/.settings/stm32cubeide.project.prefs b/CM7/.settings/stm32cubeide.project.prefs index 316c569..21ec017 100644 --- a/CM7/.settings/stm32cubeide.project.prefs +++ b/CM7/.settings/stm32cubeide.project.prefs @@ -1,4 +1,4 @@ 635E684B79701B039C64EA45C3F84D30=EB92BDC8CA3A439D88C6F56E4DDF7E32 -8DF89ED150041C4CBC7CB9A9CAA90856=E805E3BE0E38C82E0E591B5E374240D4 -DC22A860405A8BF2F2C095E5B6529F12=31D4B83A11F9313509F3357E4EAAF47F +8DF89ED150041C4CBC7CB9A9CAA90856=AC892FC3BC99DC619B57AAD46AD701C9 +DC22A860405A8BF2F2C095E5B6529F12=AC892FC3BC99DC619B57AAD46AD701C9 eclipse.preferences.version=1 diff --git a/CM7/Components/Data.hpp b/CM7/Components/Data.hpp new file mode 100644 index 0000000..e3e3da6 --- /dev/null +++ b/CM7/Components/Data.hpp @@ -0,0 +1,55 @@ +/* + * Data.hpp + * + */ + +#ifndef DATA_HPP_ +#define DATA_HPP_ + + +#include +#include "SystemDefines.hpp" + +typedef union logFloat { + float f; + uint8_t u8[4]; + uint32_t u32; +} logFloat; + +typedef struct IMUData { + logFloat xAccel; + logFloat yAccel; + logFloat zAccel; +} IMUData; + +typedef struct AltimeterData { + logFloat altitude; + logFloat temp; +} AltimeterData; + +/* + * mario = Experiment Board LPS22HH U3 + * luigi = Experiment Board LPS22HH U4 + * bowser = Main Board MS5611 U4 + */ +typedef struct BarometerData { + logFloat marioPressure; + logFloat marioTemperature; + logFloat luigiPressure; + logFloat luigiTemperature; + logFloat bowserPressure; + logFloat bowserTemperature; +} BarometerData; + +/* + * Data Containers + * Acts as a pointer to the other data structs alongside a timestamp for logging to flash. + */ +typedef struct AllData { + IMUData* imuData; + AltimeterData* altimeterData; + BarometerData* barometerData; + logFloat time; +} AllData; + +#endif /* DATA_HPP_ */ diff --git a/CM7/Components/Debug/DebugTask.cpp b/CM7/Components/Debug/DebugTask.cpp index 49de559..10a6512 100644 --- a/CM7/Components/Debug/DebugTask.cpp +++ b/CM7/Components/Debug/DebugTask.cpp @@ -16,6 +16,7 @@ // External Tasks (to send debug commands to) #include "FlightTask.hpp" #include "GPIO.hpp" +#include "FlashTask//Inc//FlashTask.hpp" /* Macros --------------------------------------------------------------------*/ @@ -121,6 +122,22 @@ void DebugTask::HandleDebugMessage(const char* msg) SOAR_PRINT("Current System Free Heap: %d Bytes\n", xPortGetFreeHeapSize()); SOAR_PRINT("Lowest Ever Free Heap: %d Bytes\n", xPortGetMinimumEverFreeHeapSize()); SOAR_PRINT("Debug Task Runtime \t: %d ms\n\n", TICKS_TO_MS(xTaskGetTickCount())); + } else if (strcmp(msg,"testflash") == 0) { //TODO delete me + SOAR_PRINT("testing"); + Command test(TASK_SPECIFIC_COMMAND, FHT_GROUND); + uint8_t testData = 230; + test.CopyDataToCommand(&testData, 1); + FlashTask::Inst().GetEventQueue()->Send(test); + + Command test2(TASK_SPECIFIC_COMMAND, FHT_APOGEE); + uint8_t test2Data = 230; + test2.CopyDataToCommand(&test2Data, 1); + FlashTask::Inst().GetEventQueue()->Send(test2); + + } else if (strcmp(msg, "eraseflash") == 0){ + SOAR_PRINT("Erasing..."); + Command erase(TASK_SPECIFIC_COMMAND, FHT_ERASE); + FlashTask::Inst().GetEventQueue()->Send(erase); } else { // Single character command, or unknown command diff --git a/CM7/Components/FlashTask/FlashTask.cpp b/CM7/Components/FlashTask/FlashTask.cpp new file mode 100644 index 0000000..d2672d1 --- /dev/null +++ b/CM7/Components/FlashTask/FlashTask.cpp @@ -0,0 +1,278 @@ +/* + * FlashFSHandler.cpp + * + * Created on: Jun 8, 2024 + * Author: goada + */ + +#include "Command.hpp" +#include "Task.hpp" +#include "FlashTask//Inc//FlashTask.hpp" +#include "Data.hpp" + +FlashTask::FlashTask() : Task(FLASH_TASK_QUEUE_DEPTH_OBJS) +{ +} + +void FlashTask::InitTask() +{ + // Make sure the task is not already initialized + SOAR_ASSERT(rtTaskHandle == nullptr, "Cannot initialize flash task twice"); + + BaseType_t rtValue = + xTaskCreate((TaskFunction_t)FlashTask::RunTask, + (const char*)"FlashTask", + (uint16_t)FLASH_TASK_STACK_DEPTH_WORDS, + (void*)this, + (UBaseType_t)FLASH_TASK_RTOS_PRIORITY, + (TaskHandle_t*)&rtTaskHandle); + + SOAR_ASSERT(rtValue == pdPASS, "FlashTask::InitTask() - xTaskCreate() failed"); +} + + +void FlashTask::Run() +{ + + while(flashChipHandle.init() != FLASH_OK) {osDelay(30);} + uint8_t buf = 0xff; + stateLoggingAddress = 0; + do + { + flashChipHandle.read(&buf, stateLoggingAddress, 1); + stateLoggingAddress += 20; + } while (buf == 0); + + address.u32 = stateLoggingAddress; + stateLoggingAddress -= 20; + buf = 0; + flashChipHandle.write(&buf, stateLoggingAddress, 1); + + while (1) { + + //Process commands in blocking mode + Command cm; + bool res = qEvtQueue->ReceiveWait(cm); + if(res) + handleCommand(cm); + + } +} + + +void FlashTask::handleCommand(Command& com) +{ + switch(com.GetCommand()) + { + case TASK_SPECIFIC_COMMAND: { + switch (com.GetTaskCommand()) + { + case FHT_WRITE_DATA: { + /* Expects an logFloat* array where: + * - Element 1 is a pointer to an AllData set (cast as uint16_t*) + * - 2 is a pointer to the altitude to be recorded + */ + + logFloat* toWrite[13] = + { + &(((AllData*)com.GetDataPointer())->time), + &(((AllData*)com.GetDataPointer())->imuData->xAccel), + &(((AllData*)com.GetDataPointer())->imuData->yAccel), + &(((AllData*)com.GetDataPointer())->imuData->zAccel), + &(((AllData*)com.GetDataPointer())->altimeterData->altitude), + &(((AllData*)com.GetDataPointer())->altimeterData->temp), + &(((AllData*)com.GetDataPointer())->barometerData->marioPressure), + &(((AllData*)com.GetDataPointer())->barometerData->marioTemperature), + &(((AllData*)com.GetDataPointer())->barometerData->luigiPressure), + &(((AllData*)com.GetDataPointer())->barometerData->luigiTemperature), + &(((AllData*)com.GetDataPointer())->barometerData->bowserPressure), + &(((AllData*)com.GetDataPointer())->barometerData->bowserTemperature), + (logFloat*)(com.GetDataPointer() + 1) + }; + + for (uint8_t i = 0; i < 13; i++) + { + if (address.u32 <= 100000000) + { + flashChipHandle.write(toWrite[i]->u8, address.u32, 4); + address.u32 += 4; + } else { + return; + } + + } + break; + } + case FHT_APOGEE: { + flashChipHandle.write(com.GetDataPointer(), stateLoggingAddress + 5, 4); + break; + } + case FHT_MAIN_1: { + flashChipHandle.write(com.GetDataPointer(), stateLoggingAddress + 7, 4); + break; + } + case FHT_MAIN_2: { + flashChipHandle.write(com.GetDataPointer(), stateLoggingAddress + 13, 4); + break; + } + case FHT_GROUND: { + flashChipHandle.write(com.GetDataPointer(), stateLoggingAddress + 17, 4); + flashChipHandle.write(address.u8, stateLoggingAddress + 1, 4); + break; + } + case FHT_ERASE: { + flashChipHandle.eraseChip(); + SOAR_PRINT("done\n"); + break; + } + } + } + default: + break; + } +} + + +/* +bool FlashFileSystem::Init() { + int mountattempts = 0; + e_flash_status f = flashChipHandle.init(); + if(f == FLASH_OK) { + SOAR_PRINT("Initialized flash chip\n"); + } else { + SOAR_PRINT("Could not initialize flash chip.\n"); + return false; + } + +#if 0 + flashChipHandle.eraseChip(); + uint8_t* test_data = new uint8_t[5000]; + for(int i = 0; i < 5000; i++) { + test_data[i] = i % 256; + } + flashChipHandle.write(test_data, 0x00, 5000); + memset(test_data,0x09,5000); + flashChipHandle.read(test_data, 0x00, 5000); + for(auto i = 0; i < 5000; i++) { + if(test_data[i] != i%256) { + SOAR_PRINT("Read fail at %d, wanted %d, was %d\n",i, i%256, test_data[i]); + } + } + SOAR_PRINT("Read complete 1\n"); + + + for(int i = 0; i < 5000; i++) { + test_data[i] = (i*i) % 256; + } + flashChipHandle.write(test_data, 2001, 5000); + memset(test_data,0x09,5000); + flashChipHandle.read(test_data, 2001, 5000); + for(auto i = 0; i < 5000; i++) { + if(test_data[i] != (i*i)%256) { + SOAR_PRINT("Read fail at %d, wanted %d, was %d\n",i, (i*i)%256, test_data[i]); + } + } + + SOAR_PRINT("Read complete 2\n"); + //flashChipHandle.eraseSmallestSection(0x62); + //flashChipHandle.write(test_data, 0x62, sizeof(test_data)); + //memset(test_data,0x00,sizeof(test_data)); + //flashChipHandle.read(test_data, 0x62, sizeof(test_data)); +#endif + + return true; +}*/ + +/* +void FlashFileSystem::TestVerify() { + + OpenFile("test.hi"); + char testbuf[123]; + for(size_t i = 0; i < sizeof(testbuf); i++) { + testbuf[i] = i%('~'-'!') + '!'; + } + testbuf[sizeof(testbuf)-1] = 0x00; + + lfs_file_write(&LFS, ¤tOpenFile, testbuf, sizeof(testbuf)); + lfs_file_sync(&LFS, ¤tOpenFile); + + printf("Written: %s\n",testbuf); + + memset(testbuf,0x00,sizeof(testbuf)); + + lfs_file_read(&LFS, ¤tOpenFile, testbuf, sizeof(testbuf)); + + printf("Recovered: %s\n",testbuf); + + CloseFile(¤tOpenFile); +} +/* +bool FlashFileSystem::OpenFile(const char *const filename) { + if(currentOpenFileValid) { + CloseFile(¤tOpenFile); + } + + int e = lfs_file_open(&LFS, ¤tOpenFile, filename, LFS_O_RDWR | LFS_O_CREAT | LFS_O_TRUNC); + if(e == 0) { + currentOpenFileValid = true; + return true; + } else { + return false; + } +} + +void FlashFileSystem::CloseFile(lfs_file_t *file) { + lfs_file_close(&LFS, file); + currentOpenFileValid = false; +} + +int lfs_ReadWrapper (const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, void *buffer, lfs_size_t size) { + SOAR_PRINT("readwrapper\n"); + + e_flash_status s = ((FlashFileSystem*)(c->context))->flashChipHandle.read((uint8_t*)buffer, block*c->block_size + off, size); + + while(((FlashFileSystem*)(c->context))->flashChipHandle.isBusy()); + return s; +} + + +int lfs_WriteWrapper (const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size) { + SOAR_PRINT("writewrapper\n"); + e_flash_status s = ((FlashFileSystem*)(c->context))->flashChipHandle.write((uint8_t*)buffer, block*c->block_size + off, size); + + while(((FlashFileSystem*)(c->context))->flashChipHandle.isBusy()); + return s; +} + +int lfs_SyncWrapper (const struct lfs_config *c) { + SOAR_PRINT("sync wrapper\n"); + return 0; +} + +int lfs_EraseWrapper (const struct lfs_config *c, lfs_block_t block) { + SOAR_PRINT("erasewrapper\n"); + e_flash_status s = ((FlashFileSystem*)(c->context))->flashChipHandle.eraseSmallestSection(block*c->block_size); + + while(((FlashFileSystem*)(c->context))->flashChipHandle.isBusy()); + return s; +} + +bool FlashFileSystem::WriteAt(uint8_t *data, size_t size, uint32_t addr) { + return flashChipHandle.write(data, addr, size) == FLASH_OK; +} + +bool FlashFileSystem::ReadAt(uint8_t *dataout, size_t size, uint32_t addr) { + return flashChipHandle.read(dataout, addr, size) == FLASH_OK; +} + +bool FlashFileSystem::EraseBlock(uint32_t addr) { + return flashChipHandle.eraseSmallestSection(addr) == FLASH_OK; +} + +bool FlashFileSystem::EraseChip() { + return flashChipHandle.eraseChip() == FLASH_OK; +} +*/ + diff --git a/CM7/Components/FlashTask/Inc/FlashTask.hpp b/CM7/Components/FlashTask/Inc/FlashTask.hpp new file mode 100644 index 0000000..b54ce7b --- /dev/null +++ b/CM7/Components/FlashTask/Inc/FlashTask.hpp @@ -0,0 +1,123 @@ +/* + * FlashFSHandler.cpp + * + * Created on: Jun 8, 2024 + * Author: goada + */ + + +/*Notes on the organization of things: + * + * - First page is reserved for the following: + * - 8 0's to flag where data is (and prevent it from being overwritten) + * - 32 bit address of last raw date write + * - 32 bit time of apoggee detection (transition from launch to drogue states) + * - 2x 32 bit time of main detection (transition from drouge to main states) + * - 32 bit time of ground detection (transition from main to postlaunch) + * + * - Every page is written as 5 writes of 400 bits + * - 1 copy of an AllData struct (descibed in data.hpp) + * - unsigned 16 bit filtered altitude + * + */ + +#include "Sensors//Inc//W25N01GVSFIG.hpp" +#include "Task.h" +#include "SystemDefines.hpp" +#include "Data.hpp" + +enum firstPageDataType { + lastWriteAddress, + apogeeTime, + mainDeactivateTime, + mainAcitvateTime, + groundTime +}; + +enum flashTaskCommands { + FHT_WRITE_DATA, + FHT_APOGEE, + FHT_MAIN_1, + FHT_MAIN_2, + FHT_GROUND, + FHT_ERASE +}; + + +class FlashTask: public Task { +public: + + static FlashTask& Inst() { + static FlashTask inst; + return inst; + } + + void InitTask(); + + bool logTransition(firstPageDataType); + + bool write(struct AllData* data, uint16_t altitude); + +protected: + + static void RunTask(void* Pvparams) {FlashTask::Inst().Run();} + void Run(); + + void handleCommand(Command& com); + +private: + + FlashTask(); // Private constructor + FlashTask(const FlashTask&); // Prevent copy-construction + FlashTask& operator=(const FlashTask&); // Prevent assignment + + void TestVerify(); + + W25N01GVSFIG flashChipHandle = {GPIOB, GPIO_PIN_10, nullptr, 0, 0}; + + logFloat address; + uint8_t stateLoggingAddress; + + /* + bool WriteAt(uint8_t* data, size_t size, uint32_t addr); + bool ReadAt(uint8_t* dataout, size_t size, uint32_t addr); + bool EraseBlock(uint32_t addr); + bool EraseChip(); + + + bool initialized; + + lfs_t LFS; + lfs_file_t currentOpenFile; + bool currentOpenFileValid; + + + const lfs_config LFSCONFIG = { + .context = this, + .read = lfs_ReadWrapper, + .prog = lfs_WriteWrapper, + .erase = lfs_EraseWrapper, + .sync = lfs_SyncWrapper, + + + + .read_size = 16, + .prog_size = 16, + .block_size = 0x20000, + .block_count = 1024, + .block_cycles = 500, + .cache_size =16, + .lookahead_size = 16, + + //.read_buffer = readbuf, + //.prog_buffer = progbuf, + //.lookahead_buffer = lookbuf + + + + + + + }; + */ +}; diff --git a/CM7/Components/FlightControl/FlightTask.cpp b/CM7/Components/FlightControl/FlightTask.cpp index 196a7a6..1469b37 100644 --- a/CM7/Components/FlightControl/FlightTask.cpp +++ b/CM7/Components/FlightControl/FlightTask.cpp @@ -9,6 +9,8 @@ #include "GPIO.hpp" #include "SystemDefines.hpp" +#include "FlashTask//Inc//FlashTask.hpp" //TODO delete me + /** * @brief Constructor for FlightTask */ @@ -45,6 +47,7 @@ void FlightTask::Run(void * pvParams) osm_ = new OsirisSM(OS_PRELAUNCH, true); + while (1) { //Process commands in blocking mode diff --git a/CM7/Components/Sensors/Inc/W25N01GVSFIG.hpp b/CM7/Components/Sensors/Inc/W25N01GVSFIG.hpp new file mode 100644 index 0000000..6dd0559 --- /dev/null +++ b/CM7/Components/Sensors/Inc/W25N01GVSFIG.hpp @@ -0,0 +1,104 @@ +/** + * @file W25N01GVSFIG.hpp + * @brief Header file for the W25N01 Flash chip on the SAC 2024 payload + * @author Kail Olson + * @date May 18th, 2024 +*/ + +// Opcodes +#define OP_W25N01_DEVICE_RESET 0xFFU +#define OP_W25N01_JEDEC_ID 0x9FU +#define OP_W25N01_READ_SR 0x0FU +#define OP_W25N01_WRITE_SR 0x1FU +#define OP_W25N01_WRITE_EN 0x06U +#define OP_W25N01_WRITE_DISABLE 0x04U +#define OP_W25N01_BBM_SWAP_BLOCKS 0xA1U +#define OP_W25N01_READ_BBM_LUT 0xA5U +#define OP_W25N01_ECC_FAIL_PG_ADDR 0xA9U +#define OP_W25N01_BLOCK_ERASE 0xD8U +#define OP_W25N01_LOAD_PGM_DATA 0x02U +#define OP_W25N01_RAND_LOAD_PGM_DATA 0x84U +#define OP_W25N01_Q_LOAD_PGM_DATA 0x32U +#define OP_W25N01_Q_RAND_LOAD_PGM_DATA 0x34U +#define OP_W25N01_PGM_EXECUTE 0x10U +#define OP_W25N01_PG_DATA_READ 0x13U +#define OP_W25N01_READ 0x03U +#define OP_W25N01_FAST_READ 0x0BU +#define OP_W25N01_FAST_READ_4B_ADDR 0x0CU +#define OP_W25N01_DO_FAST_READ 0x3BU +#define OP_W25N01_DO_FAST_READ_4B_ADDR 0x3CU +#define OP_W25N01_QO_FAST_READ 0x6BU +#define OP_W25N01_QO_FAST_READ_4B_ADDR 0x6CU +#define OP_W25N01_DIO_FAST_READ 0xBBU +#define OP_W25N01_DIO_FAST_READ_4B_ADDR 0xBCU +#define OP_W25N01_QIO_FAST_READ 0xEBU +#define OP_W25N01_QIO_FAST_READ_4B_ADDR 0xECU + +// Special addresses +#define ADDR_W25N01_SR1 0xA0U +#define ADDR_W25N01_SR2 0xB0U +#define ADDR_W25N01_SR3 0xC0U + +// Special keys +#define KEY_W25N01_MFG_ID 0xEFU +#define KEY_W25N01_DEVICE_ID_U 0xAAU +#define KEY_W25N01_DEVICE_ID_L 0x21U + +// Bitmasks +#define MASK_W25N01_SR2_RESERVED_BITS 0x07U +#define MASK_W25N01_SR3_P_FAIL 0x08U +#define MASK_W25N01_SR3_E_FAIL 0x04U +#define MASK_W25N01_SR3_WEL 0x02U +#define MASK_W25N01_SR3_BUSY 0x01U + +// Special numbers +#define INT_W25N01_COLS_PER_PAGE 2112U +#define INT_W25N01_PAGES_PER_BLOCK 64U +#define INT_W25N01_NUM_BLOCKS 1024U + +// For SPI driver +#define SPI_W25N01_TIMEOUT 1000U + +#include +#include +#include "main.h" + +// Enum definition +enum e_flash_status { + FLASH_OK, + FLASH_NOT_OK, +}; +typedef enum e_flash_status e_flash_status; + +class W25N01GVSFIG { + private: + // Member variables + GPIO_TypeDef* m_GPIOx; + uint16_t m_GPIO_Pin; + QSPI_HandleTypeDef* m_HSPIPtr; + uint16_t m_pageAddress; + uint16_t m_columnAddress; + + // Private member functions + inline void m_updatePageAndColumnAddress(uint32_t address); + void m_pageDataRead(); + e_flash_status m_writeEnable(); + e_flash_status m_writeStatReg(uint8_t SRNumber, uint8_t val); + e_flash_status m_executeProgram(); + uint8_t m_checkSR(uint8_t SRNumber); + //bool m_QSPIWrite(uint8_t* data, uint16_t size); + + public: + // Constructor and destructor + W25N01GVSFIG(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, QSPI_HandleTypeDef* HSPIPtr, uint16_t pageAddress, uint16_t columnAddress); + ~W25N01GVSFIG(); + + // Public member functions + e_flash_status init(); + e_flash_status write(uint8_t* data, uint32_t address, uint32_t size); + e_flash_status read(uint8_t* data, uint32_t address, uint32_t size); + e_flash_status eraseChip(); + e_flash_status eraseSmallestSection(uint32_t address); + uint32_t getSmallestErasableSectionSize(); + uint8_t isBusy(); +}; diff --git a/CM7/Components/Sensors/W25N01GVSFIG.cpp b/CM7/Components/Sensors/W25N01GVSFIG.cpp new file mode 100644 index 0000000..d4546c6 --- /dev/null +++ b/CM7/Components/Sensors/W25N01GVSFIG.cpp @@ -0,0 +1,547 @@ +/** + * @file W25N01GVSFIG.cpp + * @brief Contains code for the W25N01 Flash chip on the SAC 2024 payload + * @author Kail Olson + * @date May 18th, 2024 +*/ + +#include "Inc//W25N01GVSFIG.hpp" +#include "SystemDefines.hpp" +#include + +// Constructor +W25N01GVSFIG::W25N01GVSFIG(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, QSPI_HandleTypeDef* HSPIPtr, uint16_t pageAddress, uint16_t columnAddress) + : m_GPIOx { GPIOx }, + m_GPIO_Pin { GPIO_Pin }, + m_HSPIPtr { HSPIPtr }, + m_pageAddress { pageAddress }, + m_columnAddress { columnAddress } + { /*No other function*/ } + + + // Destructor + W25N01GVSFIG::~W25N01GVSFIG() + + { /*No other function*/ + + } + + +// Private member functions +inline void W25N01GVSFIG::m_updatePageAndColumnAddress(uint32_t address) { + m_pageAddress = uint16_t (address / INT_W25N01_COLS_PER_PAGE); + m_columnAddress = uint16_t (address % INT_W25N01_COLS_PER_PAGE); +} + +void W25N01GVSFIG::m_pageDataRead() { + // Create message + uint8_t messagePtr[4]; + messagePtr[0] = OP_W25N01_PG_DATA_READ; + messagePtr[1] = 0x00U; // Garbage + messagePtr[2] = (uint8_t) ((m_pageAddress & 0xFF00) >> 8U); + messagePtr[3] = (uint8_t) (m_pageAddress & 0x00FF); + + static QSPI_CommandTypeDef cmd; + cmd.Address = 0x00; + cmd.AddressMode = QSPI_ADDRESS_NONE; + cmd.AddressSize = 0; + cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + cmd.AlternateBytes = 0; + cmd.AlternateBytesSize = 0; + cmd.DataMode = QSPI_DATA_1_LINE; + cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + cmd.DdrMode = QSPI_DDR_MODE_DISABLE; + cmd.DummyCycles = 0; + cmd.Instruction = OP_W25N01_PG_DATA_READ; + cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; + cmd.NbData=3; + cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + // Transmit "Page Data Read" instruction + if(HAL_QSPI_Command(m_HSPIPtr, &cmd, SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not set qspi command\n"); + } + if(HAL_QSPI_Transmit(m_HSPIPtr, &messagePtr[1], SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not transmit data\n"); + } + + + // Wait 1ms (minimum 5us) required before page is fully read + HAL_Delay(1); + + return; +} + +e_flash_status W25N01GVSFIG::m_writeEnable() { + e_flash_status flashStatus = FLASH_OK; + + static QSPI_CommandTypeDef cmd; + cmd.Address = 0x00; + cmd.AddressMode = QSPI_ADDRESS_NONE; + cmd.AddressSize = QSPI_ADDRESS_32_BITS; + cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + cmd.AlternateBytes = 0; + cmd.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE; + cmd.DataMode = QSPI_DATA_NONE; + cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + cmd.DdrMode = QSPI_DDR_MODE_DISABLE; + cmd.DummyCycles = 0; + cmd.Instruction = OP_W25N01_WRITE_EN; + cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; + cmd.NbData=0; + cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + if(HAL_QSPI_Command(m_HSPIPtr, &cmd, SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not set qspi command\n"); + return FLASH_NOT_OK; + } + + // Return a NOT_OK enum if the write-enable latch was not set + if (!(this->m_checkSR(3) & MASK_W25N01_SR3_WEL)) flashStatus = FLASH_NOT_OK; + + return flashStatus; +} + +e_flash_status W25N01GVSFIG::m_writeStatReg(uint8_t SRNumber, uint8_t val) { + e_flash_status flashStatus = FLASH_OK; + + static QSPI_CommandTypeDef cmd; + + if(SRNumber == 1) { + cmd.Address = ADDR_W25N01_SR1; + } else if (SRNumber == 2) { + cmd.Address = ADDR_W25N01_SR2; + } else { + cmd.Address = ADDR_W25N01_SR3; + } + + cmd.AddressMode = QSPI_ADDRESS_1_LINE; + cmd.AddressSize = QSPI_ADDRESS_8_BITS; + cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + cmd.AlternateBytes = 0; + cmd.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE; + cmd.DataMode = QSPI_DATA_1_LINE; + cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + cmd.DdrMode = QSPI_DDR_MODE_DISABLE; + cmd.DummyCycles = 0; + cmd.Instruction = OP_W25N01_WRITE_SR; + cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; + cmd.NbData=1; + cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + if(HAL_QSPI_Command(m_HSPIPtr, &cmd, SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not set qspi command\n"); + return FLASH_NOT_OK; + } + if(HAL_QSPI_Transmit(m_HSPIPtr, &val, SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not transmit data\n"); + return FLASH_NOT_OK; + } + + // Return a NOT_OK enum if the write-enable latch was not set + if (!(this->m_checkSR(3) & MASK_W25N01_SR3_WEL)) flashStatus = FLASH_NOT_OK; + + return flashStatus; +} + +e_flash_status W25N01GVSFIG::m_executeProgram() { + e_flash_status flashStatus = FLASH_OK; + + // Create message + uint8_t messagePtr[4]; + messagePtr[0] = OP_W25N01_PGM_EXECUTE; + messagePtr[1] = 0x00U; // Garbage + messagePtr[2] = (uint8_t) ((m_pageAddress & 0xFF00) >> 8U); + messagePtr[3] = (uint8_t) (m_pageAddress & 0x00FF); + + // Transmit "Program Execute" instruction + //HAL_SPI_Transmit(m_HSPIPtr, messagePtr, 4, SPI_W25N01_TIMEOUT); + + static QSPI_CommandTypeDef cmd; + cmd.Address = 0x00; + cmd.AddressMode = QSPI_ADDRESS_NONE; + cmd.AddressSize = QSPI_ADDRESS_32_BITS; + cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + cmd.AlternateBytes = 0; + cmd.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE; + cmd.DataMode = QSPI_DATA_1_LINE; + cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + cmd.DdrMode = QSPI_DDR_MODE_DISABLE; + cmd.DummyCycles = 0; + cmd.Instruction = OP_W25N01_PGM_EXECUTE; + cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; + cmd.NbData=3; + cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + if(HAL_QSPI_Command(m_HSPIPtr, &cmd, SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not set qspi command\n"); + return FLASH_NOT_OK; + } + if(HAL_QSPI_Transmit(m_HSPIPtr, messagePtr+1, SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not set qspi command\n"); + return FLASH_NOT_OK; + } + + // Wait 1ms (minimum 10us as per datasheet) + HAL_Delay(1); + + // Return a NOT_OK enum if the program-fail bit was set + if (this->m_checkSR(3) & MASK_W25N01_SR3_P_FAIL) flashStatus = FLASH_NOT_OK; + + return flashStatus; +} + +uint8_t W25N01GVSFIG::m_checkSR(uint8_t SRNumber) { + uint8_t SRValue = 0xaa; + + // Prepare message + uint8_t* messagePtr = new uint8_t[2]; + messagePtr[0] = OP_W25N01_READ_SR; + if (SRNumber == 1) { + messagePtr[1] = ADDR_W25N01_SR1; + } else if (SRNumber == 2) { + messagePtr[1] = ADDR_W25N01_SR2; + } else { + messagePtr[1] = ADDR_W25N01_SR3; + } + + static QSPI_CommandTypeDef cmd; + cmd.Address = messagePtr[1]; + cmd.AddressMode = QSPI_ADDRESS_1_LINE; + cmd.AddressSize = QSPI_ADDRESS_8_BITS; + cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + cmd.AlternateBytes = 0; + cmd.AlternateBytesSize = 0; + cmd.DataMode = QSPI_DATA_1_LINE; + cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + cmd.DdrMode = QSPI_DDR_MODE_DISABLE; + cmd.DummyCycles = 0; + cmd.Instruction = OP_W25N01_READ_SR; + cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; + cmd.NbData=1; + cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + if(HAL_QSPI_Command(m_HSPIPtr, &cmd, SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not set qspi command\n"); + return FLASH_NOT_OK; + } +// if(HAL_QSPI_Transmit(m_HSPIPtr, &messagePtr[1],SPI_W25N01_TIMEOUT) != HAL_OK) { +// SOAR_PRINT("Could not set qspi transmit\n"); +// return FLASH_NOT_OK; +// } + + + + // Transmit "Read SR" instruction + //HAL_SPI_Transmit(m_HSPIPtr, messagePtr, 2, SPI_W25N01_TIMEOUT); + + // Receive SR value + //HAL_SPI_Receive(m_HSPIPtr, (uint8_t*) &SRValue, 1, SPI_W25N01_TIMEOUT); + + HAL_QSPI_Receive(m_HSPIPtr, &SRValue, SPI_W25N01_TIMEOUT); + + return SRValue; +} + + +// Public member functions +e_flash_status W25N01GVSFIG::init() { + e_flash_status flashStatus = FLASH_OK; + + if(m_HSPIPtr ==nullptr) { + m_HSPIPtr = new QSPI_HandleTypeDef; + + m_HSPIPtr->Init.ClockPrescaler = 255; + m_HSPIPtr->Init.FifoThreshold = 4; + m_HSPIPtr->Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE; + m_HSPIPtr->Init.FlashSize = 26; + m_HSPIPtr->Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_8_CYCLE; + m_HSPIPtr->Init.ClockMode = QSPI_CLOCK_MODE_0; + m_HSPIPtr->Init.FlashID = QSPI_FLASH_ID_1; + m_HSPIPtr->Init.DualFlash = QSPI_DUALFLASH_DISABLE; + + m_HSPIPtr->Instance = QUADSPI; + + if(HAL_QSPI_Init(m_HSPIPtr) != HAL_OK) { + SOAR_PRINT("Could not init QSPI\n"); + return FLASH_NOT_OK; + } + } + + static QSPI_CommandTypeDef cmd; + cmd.Address = 0x00; + cmd.AddressMode = QSPI_ADDRESS_NONE; + cmd.AddressSize = QSPI_ADDRESS_32_BITS; + cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + cmd.AlternateBytes = 0; + cmd.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE; + cmd.DataMode = QSPI_DATA_1_LINE; + cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + cmd.DdrMode = QSPI_DDR_MODE_DISABLE; + cmd.DummyCycles = 8; + cmd.Instruction = OP_W25N01_JEDEC_ID; + cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; + cmd.NbData=3; // JEDEC ID plus two device IDs + cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + if(HAL_QSPI_Command(m_HSPIPtr, &cmd, SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not set qspi command\n"); + return FLASH_NOT_OK; + } + + // Create receive buffer + uint8_t receivedMessagePtr[3]; + memset(receivedMessagePtr,0x00,3); + + //Receive IDs + HAL_StatusTypeDef result = HAL_QSPI_Receive(m_HSPIPtr, receivedMessagePtr, SPI_W25N01_TIMEOUT); + + if(result != HAL_OK) { + SOAR_PRINT("Could not receive JEDEC bytes\n"); + return FLASH_NOT_OK; + } else { +// SOAR_PRINT("Received: %x %x %x\n",receivedMessagePtr[0],receivedMessagePtr[1],receivedMessagePtr[2]); + } + + // Check for correct received message + if (receivedMessagePtr[0] != KEY_W25N01_MFG_ID) flashStatus = FLASH_NOT_OK; + if (receivedMessagePtr[1] != KEY_W25N01_DEVICE_ID_U) flashStatus = FLASH_NOT_OK; + if (receivedMessagePtr[2] != KEY_W25N01_DEVICE_ID_L) flashStatus = FLASH_NOT_OK; + + // Enable writing + this->m_writeEnable(); + + this->m_writeStatReg(1, 0x00); // SR-1 settings for Osiris application + + + // Enable writing + this->m_writeEnable(); + + this->m_writeStatReg(2, 0x08);// SR-2 settings for Osiris application (BUF=1) + + + // Check that the SR registers were correctly configured + if (this->m_checkSR(1) != 0x00U) flashStatus = FLASH_NOT_OK; + if ((this->m_checkSR(2) & ~MASK_W25N01_SR2_RESERVED_BITS) != 0x08U) flashStatus = FLASH_NOT_OK; + + // Return + return flashStatus; +} + +e_flash_status W25N01GVSFIG::write(uint8_t* data, uint32_t address, uint32_t size) { + e_flash_status flashStatus = FLASH_OK; + + + // Convert given address to page and column + this->m_updatePageAndColumnAddress(address); + + + // Writing data + uint32_t remainingData = size; + uint32_t sizeToWrite = 0; + uint32_t dataOffset = 0; + + if (remainingData > (INT_W25N01_COLS_PER_PAGE - m_columnAddress)) sizeToWrite = INT_W25N01_COLS_PER_PAGE - m_columnAddress; + else sizeToWrite = remainingData; + + while (remainingData > 0) { + // Read page data into buffer + this->m_pageDataRead(); + + // Enable writing + this->m_writeEnable(); + + + static QSPI_CommandTypeDef cmd; + cmd.Address = m_columnAddress; + cmd.AddressMode = QSPI_ADDRESS_1_LINE; + cmd.AddressSize = QSPI_ADDRESS_16_BITS; + cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + cmd.AlternateBytes = 0; + cmd.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE; + cmd.DataMode = QSPI_DATA_1_LINE; + cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + cmd.DdrMode = QSPI_DDR_MODE_DISABLE; + cmd.DummyCycles = 0; + cmd.Instruction = OP_W25N01_RAND_LOAD_PGM_DATA; + cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; + cmd.NbData=sizeToWrite; + cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + // Transmit "Random Load Program Data" instruction + //HAL_SPI_Transmit(m_HSPIPtr, messagePtr, 3, SPI_W25N01_TIMEOUT); + + if(HAL_QSPI_Command(m_HSPIPtr, &cmd, SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not set qspi command\n"); + return FLASH_NOT_OK; + } + + if(HAL_QSPI_Transmit(m_HSPIPtr, &data[dataOffset], SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not set qspi command\n"); + return FLASH_NOT_OK; + } + + // Enable writing + this->m_writeEnable(); + + // Execute program + if (this->m_executeProgram() != FLASH_OK) return FLASH_NOT_OK; // Evil return but who cares + + // Subtract written data from size + remainingData -= sizeToWrite; + + // Set offset + dataOffset += sizeToWrite; + + // Determine next "sizeToWrite" + if (remainingData > INT_W25N01_COLS_PER_PAGE) sizeToWrite = INT_W25N01_COLS_PER_PAGE; + else sizeToWrite = remainingData; + + + // Increment page address and set column address to 0 + m_pageAddress++; + m_columnAddress = 0; + } + + return flashStatus; +} + +e_flash_status W25N01GVSFIG::eraseChip() { + // Loop through all blocks and erase + for (uint32_t i = 0; i < INT_W25N01_NUM_BLOCKS; i++) { + if (this->eraseSmallestSection(i * INT_W25N01_PAGES_PER_BLOCK * INT_W25N01_COLS_PER_PAGE) != FLASH_OK) return FLASH_NOT_OK; + } + + return FLASH_OK; +} + +e_flash_status W25N01GVSFIG::eraseSmallestSection(uint32_t address) { + e_flash_status flashStatus = FLASH_OK; + + // Update page and column address + this->m_updatePageAndColumnAddress(address); + + // Prepare message + uint8_t messagePtr[4]; + messagePtr[0] = OP_W25N01_BLOCK_ERASE; + messagePtr[1] = 0x00U; // Garbage + messagePtr[2] = (uint8_t) ((m_pageAddress & 0xFF00U) >> 8U); + messagePtr[3] = (uint8_t) (m_pageAddress & 0x00FFU); + + // Enable writing + this->m_writeEnable(); + + static QSPI_CommandTypeDef cmd; + cmd.Address = 0x00; + cmd.AddressMode = QSPI_ADDRESS_NONE; + cmd.AddressSize = QSPI_ADDRESS_32_BITS; + cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + cmd.AlternateBytes = 0; + cmd.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE; + cmd.DataMode = QSPI_DATA_1_LINE; + cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + cmd.DdrMode = QSPI_DDR_MODE_DISABLE; + cmd.DummyCycles = 0; + cmd.Instruction = OP_W25N01_BLOCK_ERASE; + cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; + cmd.NbData=3; + cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + // Transmit "Erase Block" instruction + if(HAL_QSPI_Command(m_HSPIPtr, &cmd, SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not set qspi command\n"); + return FLASH_NOT_OK; + } + if(HAL_QSPI_Transmit(m_HSPIPtr, messagePtr+1, SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not set qspi command\n"); + return FLASH_NOT_OK; + } + + // Wait for 1ms (minimum 500us as per datasheet) + HAL_Delay(1); + + // Check E-FAIL bit in SR3 + if (this->m_checkSR(3) & MASK_W25N01_SR3_E_FAIL) { + flashStatus = FLASH_NOT_OK; + SOAR_PRINT("failed erase\n"); + } + + return flashStatus; +} + +uint32_t W25N01GVSFIG::getSmallestErasableSectionSize() { + return INT_W25N01_COLS_PER_PAGE * INT_W25N01_PAGES_PER_BLOCK; +} + +uint8_t W25N01GVSFIG::isBusy() { + // Return value of busy bit in SR3 + return (this->m_checkSR(3) & MASK_W25N01_SR3_BUSY); +} + +e_flash_status W25N01GVSFIG::read(uint8_t *data, uint32_t address, + uint32_t size) { + e_flash_status flashStatus = FLASH_OK; + + // Convert given address to page and column + this->m_updatePageAndColumnAddress(address); + + // Reading data + uint32_t remainingData = size; + uint32_t sizeToRead = 0; + uint32_t dataOffset = 0; + + if (remainingData > (INT_W25N01_COLS_PER_PAGE - m_columnAddress)) sizeToRead = INT_W25N01_COLS_PER_PAGE - m_columnAddress; + else sizeToRead = remainingData; + + while (remainingData > 0) { + // Read page data into buffer + this->m_pageDataRead(); + + static QSPI_CommandTypeDef cmd; + cmd.Address = m_columnAddress; + cmd.AddressMode = QSPI_ADDRESS_1_LINE; + cmd.AddressSize = QSPI_ADDRESS_16_BITS; + cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + cmd.AlternateBytes = 0; + cmd.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE; + cmd.DataMode = QSPI_DATA_1_LINE; + cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + cmd.DdrMode = QSPI_DDR_MODE_DISABLE; + cmd.DummyCycles = 8; + cmd.Instruction = OP_W25N01_READ; + cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; + cmd.NbData=sizeToRead; + cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + // Transmit "Random Load Program Data" instruction + //HAL_SPI_Transmit(m_HSPIPtr, messagePtr, 3, SPI_W25N01_TIMEOUT); + + if(HAL_QSPI_Command(m_HSPIPtr, &cmd, SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not set qspi command\n"); + return FLASH_NOT_OK; + } + + + if(HAL_QSPI_Receive(m_HSPIPtr, data+dataOffset, SPI_W25N01_TIMEOUT) != HAL_OK) { + SOAR_PRINT("Could not set qspi command\n"); + return FLASH_NOT_OK; + } + + // Subtract written data from size + remainingData -= sizeToRead; + + + // Set offset + dataOffset += sizeToRead; + + // Determine next "sizeToWrite" + if (remainingData > INT_W25N01_COLS_PER_PAGE) sizeToRead = INT_W25N01_COLS_PER_PAGE; + else sizeToRead = remainingData; + + // Increment page address and set column address to 0 + m_pageAddress++; + m_columnAddress = 0; + } + + return flashStatus; + +} diff --git a/CM7/Components/SystemDefines.hpp b/CM7/Components/SystemDefines.hpp index d5b705d..f5557fc 100644 --- a/CM7/Components/SystemDefines.hpp +++ b/CM7/Components/SystemDefines.hpp @@ -55,6 +55,11 @@ constexpr uint8_t FLIGHT_TASK_RTOS_PRIORITY = 2; // Priority of the d constexpr uint8_t FLIGHT_TASK_QUEUE_DEPTH_OBJS = 10; // Size of the debug task queue constexpr uint16_t FLIGHT_TASK_STACK_DEPTH_WORDS = 512; // Size of the debug task stack +//Flash Task +constexpr uint8_t FLASH_TASK_RTOS_PRIORITY = 2; // Priority of the FLASH task +constexpr uint8_t FLASH_TASK_QUEUE_DEPTH_OBJS = 10; // Size of the FLASH task queue +constexpr uint16_t FLASH_TASK_STACK_DEPTH_WORDS = 512; // Size of the FLASH task stack + #endif // CUBE_MAIN_SYSTEM_DEFINES_H diff --git a/CM7/Components/main_system.cpp b/CM7/Components/main_system.cpp index b3faaf8..d11e26b 100644 --- a/CM7/Components/main_system.cpp +++ b/CM7/Components/main_system.cpp @@ -13,6 +13,7 @@ #include "CubeTask.hpp" #include "DebugTask.hpp" #include "FlightTask.hpp" +#include "FlashTask//Inc//FlashTask.hpp" /* Drivers ------------------------------------------------------------------*/ namespace Driver { @@ -28,6 +29,7 @@ void run_main() { CubeTask::Inst().InitTask(); DebugTask::Inst().InitTask(); FlightTask::Inst().InitTask(); + FlashTask::Inst().InitTask(); // Print System Boot Info : Warning, don't queue more than 10 prints before scheduler starts SOAR_PRINT("\n-- SOAR SYSTEM --\n"); diff --git a/CM7/Core/Src/main.c b/CM7/Core/Src/main.c index 9d097c6..c5fb106 100644 --- a/CM7/Core/Src/main.c +++ b/CM7/Core/Src/main.c @@ -415,8 +415,8 @@ static void MX_QUADSPI_Init(void) hqspi.Init.ClockPrescaler = 255; hqspi.Init.FifoThreshold = 1; hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE; - hqspi.Init.FlashSize = 1; - hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE; + hqspi.Init.FlashSize = 26; + hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_2_CYCLE; hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0; hqspi.Init.FlashID = QSPI_FLASH_ID_1; hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE; diff --git a/Payload.ioc b/Payload.ioc index ecf18db..117500f 100644 --- a/Payload.ioc +++ b/Payload.ioc @@ -425,6 +425,9 @@ ProjectManager.UAScriptAfterPath= ProjectManager.UAScriptBeforePath= ProjectManager.UnderRoot=true ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false-CortexM7,2-MX_GPIO_Init-GPIO-false-HAL-true-CortexM7,3-MX_QUADSPI_Init-QUADSPI-false-HAL-true-CortexM7,4-MX_SPI1_Init-SPI1-false-HAL-true-CortexM7,5-MX_I2C1_Init-I2C1-false-HAL-true-CortexM7,6-MX_I2C2_Init-I2C2-false-HAL-true-CortexM7,7-MX_SPI2_Init-SPI2-false-HAL-true-CortexM7,8-MX_SPI5_Init-SPI5-false-HAL-true-CortexM7,9-MX_USART2_UART_Init-USART2-false-HAL-true-CortexM7,10-MX_UART4_Init-UART4-false-HAL-true-CortexM7,11-MX_UART5_Init-UART5-false-HAL-true-CortexM7,12-MX_USART6_UART_Init-USART6-false-LL-true-CortexM7,13-MX_SPI6_Init-SPI6-false-HAL-true-CortexM7,14-MX_FREERTOS_Init-FREERTOS_M7-false-HAL-false-CortexM7,15-MX_CRC_Init-CRC-false-HAL-true-CortexM7,1-MX_QUADSPI_Init-QUADSPI-true-HAL-false-CortexM4,2-MX_CRC_Init-CRC-true-HAL-false-CortexM4,0-MX_CORTEX_M7_Init-CORTEX_M7-false-HAL-true-CortexM7,0-MX_CORTEX_M4_Init-CORTEX_M4-false-HAL-true-CortexM4 +QUADSPI.ChipSelectHighTime=QSPI_CS_HIGH_TIME_2_CYCLE +QUADSPI.FlashSize=26 +QUADSPI.IPParameters=FlashSize,ChipSelectHighTime RCC.ADCFreq_Value=129000000 RCC.AHB12Freq_Value=64000000 RCC.AHB4Freq_Value=64000000