From 9dc449396a47cb21c5e1a62ef547ed2f24c53fee Mon Sep 17 00:00:00 2001 From: Silvano Seva Date: Tue, 8 Oct 2024 19:19:59 +0200 Subject: [PATCH] MD9600: updated nvm driver --- meson.build | 3 +- platform/drivers/CPS/cps_io_native_MD9600.c | 23 ++---- platform/drivers/NVM/nvmem_MDx.c | 7 ++ platform/drivers/display/ST7567_MD9600.c | 61 ++++++++------- platform/mcu/STM32F4xx/drivers/SPI2.c | 74 ------------------- platform/mcu/STM32F4xx/drivers/SPI2.h | 69 ----------------- .../MD-9600/hwconfig.c} | 34 ++------- platform/targets/MD-9600/hwconfig.h | 2 + platform/targets/MD-9600/pinmap.h | 2 +- platform/targets/MD-9600/platform.c | 5 +- 10 files changed, 61 insertions(+), 219 deletions(-) delete mode 100644 platform/mcu/STM32F4xx/drivers/SPI2.c delete mode 100644 platform/mcu/STM32F4xx/drivers/SPI2.h rename platform/{drivers/NVM/spiFlash_MD9600.c => targets/MD-9600/hwconfig.c} (66%) diff --git a/meson.build b/meson.build index ee0987e8..6f92f874 100644 --- a/meson.build +++ b/meson.build @@ -209,7 +209,6 @@ stm32f405_src = ['platform/mcu/STM32F4xx/boot/startup.cpp', 'platform/mcu/STM32F4xx/drivers/usb_vcom.c', 'platform/mcu/STM32F4xx/drivers/delays.cpp', 'platform/mcu/STM32F4xx/drivers/rtc.c', - 'platform/mcu/STM32F4xx/drivers/SPI2.c', 'platform/mcu/STM32F4xx/drivers/USART3.cpp', 'platform/mcu/STM32F4xx/drivers/flash.c', 'platform/mcu/STM32F4xx/drivers/rng.c', @@ -372,11 +371,11 @@ mduv3x0_def += openrtx_def + stm32f405_def + miosix_cm4f_def ## TYT MD-9600 ## md9600_src = ['platform/targets/MD-9600/platform.c', + 'platform/targets/MD-9600/hwconfig.c', 'platform/drivers/display/ST7567_MD9600.c', 'platform/drivers/keyboard/keyboard_MD9600.c', 'platform/drivers/chSelector/chSelector_MD9600.c', 'platform/drivers/baseband/radio_MD9600.cpp', - 'platform/drivers/NVM/spiFlash_MD9600.c', 'platform/drivers/CPS/cps_io_native_MD9600.c'] md9600_inc = ['platform/targets/MD-9600'] diff --git a/platform/drivers/CPS/cps_io_native_MD9600.c b/platform/drivers/CPS/cps_io_native_MD9600.c index 9968f257..6a80ea75 100644 --- a/platform/drivers/CPS/cps_io_native_MD9600.c +++ b/platform/drivers/CPS/cps_io_native_MD9600.c @@ -22,11 +22,13 @@ #include #include #include -#include +#include #include #include "cps_data_MDUV3x0.h" #include "W25Qx.h" +extern const struct nvmDevice eflash; + //static const uint32_t vfoChannelBaseAddr = 0x2EF00; /**< Base address of VFO channel */ static const uint32_t zoneBaseAddr = 0x149E0; /**< Base address of zones */ static const uint32_t zoneExtBaseAddr = 0x31000; /**< Base address of zone extensions */ @@ -36,17 +38,18 @@ static const uint32_t maxNumChannels = 3000; /**< Maximum number of cha static const uint32_t maxNumZones = 250; /**< Maximum number of zones and zone extensions in memory */ static const uint32_t maxNumContacts = 10000; /**< Maximum number of contacts in memory */ +static inline void W25Qx_readData(uint32_t addr, void *buf, size_t len) +{ + nvm_devRead(&eflash, addr, buf, len); +} /** * Used to read channel data from SPI flash into a channel_t struct */ static int _readChannelAtAddress(channel_t *channel, uint32_t addr) { - W25Qx_wakeup(); - delayUs(5); mduv3x0Channel_t chData; W25Qx_readData(addr, ((uint8_t *) &chData), sizeof(mduv3x0Channel_t)); - W25Qx_sleep(); // Check if the channel is empty #pragma GCC diagnostic ignored "-Waddress-of-packed-member" @@ -171,16 +174,12 @@ int cps_readBankHeader(bankHdr_t *b_header, uint16_t pos) { if(pos >= maxNumZones) return -1; - W25Qx_wakeup(); - delayUs(5); - mduv3x0Zone_t zoneData; mduv3x0ZoneExt_t zoneExtData; uint32_t zoneAddr = zoneBaseAddr + pos * sizeof(mduv3x0Zone_t); uint32_t zoneExtAddr = zoneExtBaseAddr + pos * sizeof(mduv3x0ZoneExt_t); W25Qx_readData(zoneAddr, ((uint8_t *) &zoneData), sizeof(mduv3x0Zone_t)); W25Qx_readData(zoneExtAddr, ((uint8_t *) &zoneExtData), sizeof(mduv3x0ZoneExt_t)); - W25Qx_sleep(); // Check if zone is empty #pragma GCC diagnostic ignored "-Waddress-of-packed-member" @@ -200,16 +199,12 @@ int cps_readBankData(uint16_t bank_pos, uint16_t ch_pos) { if(bank_pos >= maxNumZones) return -1; - W25Qx_wakeup(); - delayUs(5); - mduv3x0Zone_t zoneData; mduv3x0ZoneExt_t zoneExtData; uint32_t zoneAddr = zoneBaseAddr + bank_pos * sizeof(mduv3x0Zone_t); uint32_t zoneExtAddr = zoneExtBaseAddr + bank_pos * sizeof(mduv3x0ZoneExt_t); W25Qx_readData(zoneAddr, ((uint8_t *) &zoneData), sizeof(mduv3x0Zone_t)); W25Qx_readData(zoneExtAddr, ((uint8_t *) &zoneExtData), sizeof(mduv3x0ZoneExt_t)); - W25Qx_sleep(); // Check if zone is empty #pragma GCC diagnostic ignored "-Waddress-of-packed-member" @@ -226,13 +221,9 @@ int cps_readContact(contact_t *contact, uint16_t pos) { if(pos >= maxNumContacts) return -1; - W25Qx_wakeup(); - delayUs(5); - mduv3x0Contact_t contactData; uint32_t contactAddr = contactBaseAddr + pos * sizeof(mduv3x0Contact_t); W25Qx_readData(contactAddr, ((uint8_t *) &contactData), sizeof(mduv3x0Contact_t)); - W25Qx_sleep(); // Check if contact is empty if(wcslen((wchar_t *) contactData.name) == 0) return -1; diff --git a/platform/drivers/NVM/nvmem_MDx.c b/platform/drivers/NVM/nvmem_MDx.c index b60fcf48..10597c88 100644 --- a/platform/drivers/NVM/nvmem_MDx.c +++ b/platform/drivers/NVM/nvmem_MDx.c @@ -33,7 +33,11 @@ static const struct W25QxCfg eflashCfg = { + #ifdef PLATFORM_MD9600 + .spi = &spi2, + #else .spi = &nvm_spi, + #endif .cs = { FLASH_CS } }; @@ -67,11 +71,14 @@ static const struct nvmDescriptor nvmDevices[] = void nvm_init() { + #ifndef PLATFORM_MD9600 gpio_setMode(FLASH_CLK, ALTERNATE | ALTERNATE_FUNC(5)); gpio_setMode(FLASH_SDO, ALTERNATE | ALTERNATE_FUNC(5)); gpio_setMode(FLASH_SDI, ALTERNATE | ALTERNATE_FUNC(5)); spiStm32_init(&nvm_spi, 21000000, 0); + #endif + W25Qx_init(&eflash); } diff --git a/platform/drivers/display/ST7567_MD9600.c b/platform/drivers/display/ST7567_MD9600.c index 675e6b63..178ca40f 100644 --- a/platform/drivers/display/ST7567_MD9600.c +++ b/platform/drivers/display/ST7567_MD9600.c @@ -23,10 +23,10 @@ #include #include #include +#include #include #include #include "hwconfig.h" -#include /** @@ -57,10 +57,7 @@ static void display_renderRow(uint8_t row, uint8_t *frameBuffer) } } - for (uint8_t s = 0; s < 8; s++) - { - (void) spi2_sendRecv(tmp[s]); - } + spi_send(&spi2, tmp, 8); } } @@ -79,21 +76,24 @@ void display_init() gpio_setPin(LCD_RST); delayMs(5); + uint8_t initData[] = + { + 0x2F, /* Voltage Follower On */ + 0x81, /* Set Electronic Volume */ + 0x15, /* Contrast, initial setting */ + 0xA2, /* Set Bias = 1/9 */ + 0xA1, /* A0 Set SEG Direction */ + 0xC0, /* Set COM Direction */ + 0xA4, /* White background, black pixels */ + 0xAF, /* Set Display Enable */ + }; - spi2_lockDeviceBlocking(); + spi_acquire(&spi2); gpio_clearPin(LCD_CS); - - gpio_clearPin(LCD_RS); /* RS low -> command mode */ - (void) spi2_sendRecv(0x2F); /* Voltage Follower On */ - (void) spi2_sendRecv(0x81); /* Set Electronic Volume */ - (void) spi2_sendRecv(0x15); /* Contrast, initial setting */ - (void) spi2_sendRecv(0xA2); /* Set Bias = 1/9 */ - (void) spi2_sendRecv(0xA1); /* A0 Set SEG Direction */ - (void) spi2_sendRecv(0xC0); /* Set COM Direction */ - (void) spi2_sendRecv(0xA4); /* White background, black pixels */ - (void) spi2_sendRecv(0xAF); /* Set Display Enable */ + gpio_clearPin(LCD_RS); /* RS low -> command mode */ + spi_send(&spi2, initData, sizeof(initData)); gpio_clearPin(LCD_CS); - spi2_releaseDevice(); + spi_release(&spi2); } void display_terminate() @@ -103,21 +103,24 @@ void display_terminate() void display_renderRows(uint8_t startRow, uint8_t endRow, void *fb) { - spi2_lockDeviceBlocking(); + spi_acquire(&spi2); gpio_clearPin(LCD_CS); for(uint8_t row = startRow; row < endRow; row++) { + uint8_t command[3]; + command[0] = 0xB0 | row; /* Set Y position */ + command[1] = 0x10; /* Set X position */ + command[2] = 0x04; + gpio_clearPin(LCD_RS); /* RS low -> command mode */ - (void) spi2_sendRecv(0xB0 | row); /* Set Y position */ - (void) spi2_sendRecv(0x10); /* Set X position */ - (void) spi2_sendRecv(0x04); + spi_send(&spi2, command, 3); gpio_setPin(LCD_RS); /* RS high -> data mode */ display_renderRow(row, (uint8_t *) fb); } gpio_setPin(LCD_CS); - spi2_releaseDevice(); + spi_release(&spi2); } void display_render(void *fb) @@ -127,15 +130,17 @@ void display_render(void *fb) void display_setContrast(uint8_t contrast) { - spi2_lockDeviceBlocking(); + uint8_t command[2]; + command[0] = 0x81; /* Set Electronic Volume */ + command[1] = contrast >> 2; /* Controller contrast range is 0 - 63 */ + + spi_acquire(&spi2); gpio_clearPin(LCD_CS); - gpio_clearPin(LCD_RS); /* RS low -> command mode */ - (void) spi2_sendRecv(0x81); /* Set Electronic Volume */ - (void) spi2_sendRecv(contrast >> 2); /* Controller contrast range is 0 - 63 */ - + gpio_clearPin(LCD_RS); /* RS low -> command mode */ + spi_send(&spi2, command, 2); gpio_setPin(LCD_CS); - spi2_releaseDevice(); + spi_release(&spi2); } void display_setBacklightLevel(uint8_t level) diff --git a/platform/mcu/STM32F4xx/drivers/SPI2.c b/platform/mcu/STM32F4xx/drivers/SPI2.c deleted file mode 100644 index 9831c025..00000000 --- a/platform/mcu/STM32F4xx/drivers/SPI2.c +++ /dev/null @@ -1,74 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2021 - 2023 by Federico Amedeo Izzo IU2NUO, * - * Niccolò Izzo IU2KIN * - * Frederik Saraci IU2NRO * - * Silvano Seva IU2KWO * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see * - ***************************************************************************/ - -#include "SPI2.h" -#include -#include - -pthread_mutex_t mutex; - -void spi2_init() -{ - RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; - __DSB(); - - SPI2->CR1 = SPI_CR1_SSM /* Software managment of nCS */ - | SPI_CR1_SSI /* Force internal nCS */ - | SPI_CR1_BR_2 /* Fclock: 42MHz/32 = 1.3MHz */ - | SPI_CR1_MSTR /* Master mode */ - | SPI_CR1_SPE; /* Enable peripheral */ - - pthread_mutex_init(&mutex, NULL); -} - -void spi2_terminate() -{ - RCC->APB1ENR &= ~RCC_APB1ENR_SPI2EN; - __DSB(); - - pthread_mutex_destroy(&mutex); -} - -uint8_t spi2_sendRecv(const uint8_t val) -{ - SPI2->DR = val; - while((SPI2->SR & SPI_SR_RXNE) == 0) ; - return SPI2->DR; -} - -bool spi2_lockDevice() -{ - if(pthread_mutex_trylock(&mutex) == 0) - { - return true; - } - - return false; -} - -void spi2_lockDeviceBlocking() -{ - pthread_mutex_lock(&mutex); -} - -void spi2_releaseDevice() -{ - pthread_mutex_unlock(&mutex); -} diff --git a/platform/mcu/STM32F4xx/drivers/SPI2.h b/platform/mcu/STM32F4xx/drivers/SPI2.h deleted file mode 100644 index ea0873e8..00000000 --- a/platform/mcu/STM32F4xx/drivers/SPI2.h +++ /dev/null @@ -1,69 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2021 - 2023 by Federico Amedeo Izzo IU2NUO, * - * Niccolò Izzo IU2KIN * - * Frederik Saraci IU2NRO * - * Silvano Seva IU2KWO * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see * - ***************************************************************************/ - -#ifndef SPI2_H -#define SPI2_H - -#include -#include -#include - -/** - * Initialise SPI2 peripheral with a bus clock frequency of ~1.3MHz. - * NOTE: this driver does not configure the SPI GPIOs, which have to be put in - * alternate mode by application code. - */ -void spi2_init(); - -/** - * Shut down SPI2 peripheral. - * NOTE: is left to application code to change the operating mode of the SPI - * GPIOs - */ -void spi2_terminate(); - -/** - * Exchange one byte over the SPI bus. - * @param val: transmitted byte. - * @return incoming byte from slave device. - */ -uint8_t spi2_sendRecv(const uint8_t val); - -/** - * Acquire exclusive ownership on the SPI peripheral by locking an internal - * mutex. This function is nonblocking and returs true if mutex has been - * successfully locked by the caller. - * @return true if device has been locked. - */ -bool spi2_lockDevice(); - -/** - * Acquire exclusive ownership on the SPI peripheral by locking an internal - * mutex. In case mutex is already locked, this function blocks the execution - * flow until it becomes free again. - */ -void spi2_lockDeviceBlocking(); - -/** - * Release exclusive ownership on the SPI peripheral. - */ -void spi2_releaseDevice(); - -#endif /* SPI2_H */ diff --git a/platform/drivers/NVM/spiFlash_MD9600.c b/platform/targets/MD-9600/hwconfig.c similarity index 66% rename from platform/drivers/NVM/spiFlash_MD9600.c rename to platform/targets/MD-9600/hwconfig.c index ed90dd72..bfb5f618 100644 --- a/platform/drivers/NVM/spiFlash_MD9600.c +++ b/platform/targets/MD-9600/hwconfig.c @@ -1,8 +1,8 @@ /*************************************************************************** - * Copyright (C) 2020 - 2023 by Federico Amedeo Izzo IU2NUO, * - * Niccolò Izzo IU2KIN * - * Frederik Saraci IU2NRO * - * Silvano Seva IU2KWO * + * Copyright (C) 2024 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN, * + * Frederik Saraci IU2NRO, * + * Silvano Seva IU2KWO * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -18,28 +18,10 @@ * along with this program; if not, see * ***************************************************************************/ -#include #include -#include -#include +#include +#include -/* - * Implementation of external flash SPI interface for MD9600 devices. - */ +static pthread_mutex_t spi2Mutex; -uint8_t spiFlash_SendRecv(uint8_t val) -{ - spi2_lockDeviceBlocking(); - uint8_t x = spi2_sendRecv(val); - spi2_releaseDevice(); - - return x; -} - -void spiFlash_init() -{ -} - -void spiFlash_terminate() -{ -} +SPI_STM32_DEVICE_DEFINE(spi2, SPI2, &spi2Mutex) diff --git a/platform/targets/MD-9600/hwconfig.h b/platform/targets/MD-9600/hwconfig.h index ef6a940d..b858a2ee 100644 --- a/platform/targets/MD-9600/hwconfig.h +++ b/platform/targets/MD-9600/hwconfig.h @@ -28,6 +28,8 @@ extern "C" { #endif +extern const struct spiDevice spi2; + /* Device has a working real time clock */ #define CONFIG_RTC diff --git a/platform/targets/MD-9600/pinmap.h b/platform/targets/MD-9600/pinmap.h index d7bea610..f340b393 100644 --- a/platform/targets/MD-9600/pinmap.h +++ b/platform/targets/MD-9600/pinmap.h @@ -67,7 +67,7 @@ extern "C" { #define BEEP_OUT GPIOC,8 /* CTCSS tone */ /* SPI2, connected to external flash and LCD */ -#define FLASH_CS GPIOB,12 +#define FLASH_CS &GpioB,12 #define SPI2_CLK GPIOB,13 #define SPI2_SDO GPIOB,14 #define SPI2_SDI GPIOB,15 diff --git a/platform/targets/MD-9600/platform.c b/platform/targets/MD-9600/platform.c index a6e6dc1a..9472ea3f 100644 --- a/platform/targets/MD-9600/platform.c +++ b/platform/targets/MD-9600/platform.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include /* TODO: Hardcoded hwInfo until we implement reading from flash */ @@ -66,8 +66,7 @@ void platform_init() gpio_setMode(SPI2_CLK, ALTERNATE | ALTERNATE_FUNC(5)); gpio_setMode(SPI2_SDO, ALTERNATE | ALTERNATE_FUNC(5)); gpio_setMode(SPI2_SDI, ALTERNATE | ALTERNATE_FUNC(5)); - - spi2_init(); + spiStm32_init(&spi2, 1300000, 0); nvm_init(); /* Initialise non volatile memory manager */ toneGen_init(); /* Initialise tone generator */