mirror of https://github.com/FOME-Tech/openblt.git
Refs #1229. Added support for firmware updates from SD-card to the Olimexino-STM32F3 demo programs.
git-svn-id: https://svn.code.sf.net/p/openblt/code/trunk@1064 5dc33758-31d5-4daf-9ae8-b24bf3d40d73
This commit is contained in:
parent
f05796ba13
commit
5fd33bfabf
|
@ -51,10 +51,12 @@
|
|||
<listOptionValue builtIn="false" value="../Drivers/CMSIS/Include"/>
|
||||
<listOptionValue builtIn="false" value="../App"/>
|
||||
<listOptionValue builtIn="false" value="../Library/STM32_USB_Device_Library/Core/Inc"/>
|
||||
<listOptionValue builtIn="false" value="../Library/FatFS"/>
|
||||
<listOptionValue builtIn="false" value="../USB_DEVICE/App"/>
|
||||
<listOptionValue builtIn="false" value="../USB_DEVICE/Target"/>
|
||||
<listOptionValue builtIn="false" value="../../../../Source"/>
|
||||
<listOptionValue builtIn="false" value="../../../../Source/ARMCM4_STM32F3"/>
|
||||
<listOptionValue builtIn="false" value="../../../../Source/third_party/fatfs/src"/>
|
||||
</option>
|
||||
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c.1605971816" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c"/>
|
||||
</tool>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -38,7 +38,7 @@
|
|||
</linkedResources>
|
||||
<filteredResources>
|
||||
<filter>
|
||||
<id>1686569576442</id>
|
||||
<id>1686649539105</id>
|
||||
<name>Loader</name>
|
||||
<type>9</type>
|
||||
<matcher>
|
||||
|
@ -46,6 +46,15 @@
|
|||
<arguments>1.0-name-matches-false-false-ARMCM4_STM32F3</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>1686649539109</id>
|
||||
<name>Loader</name>
|
||||
<type>9</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-third_party</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>1686569589593</id>
|
||||
<name>Loader/ARMCM4_STM32F3</name>
|
||||
|
@ -55,6 +64,33 @@
|
|||
<arguments>1.0-name-matches-false-false-GCC</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>1686649554358</id>
|
||||
<name>Loader/third_party</name>
|
||||
<type>9</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-fatfs</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>1686649567497</id>
|
||||
<name>Loader/third_party/fatfs</name>
|
||||
<type>9</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-src</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
<filter>
|
||||
<id>1686649590858</id>
|
||||
<name>Loader/third_party/fatfs/src/option</name>
|
||||
<type>5</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-unicode.c</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
</filteredResources>
|
||||
<variableList>
|
||||
<variable>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-804685279247832828" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-666769791631151900" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
|
@ -16,7 +16,7 @@
|
|||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-804685279247832828" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-666769791631151900" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
|
|
|
@ -117,6 +117,42 @@
|
|||
#define BOOT_COM_USB_RX_MAX_DATA (63)
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* F I L E S Y S T E M I N T E R F A C E C O N F I G U R A T I O N
|
||||
****************************************************************************************/
|
||||
/* The file system interface is selected by setting the BOOT_FILE_SYS_ENABLE configurable
|
||||
* to 1. This enables support for firmware updates from a file stored on a locally
|
||||
* attached file system such as an SD-card. Note that this interface can be enabled
|
||||
* together with one of the remote communication interfaces such as UART, CAN or USB.
|
||||
*
|
||||
* Set BOOT_FILE_LOGGING_ENABLE to 1 if you would like log messages to be created during
|
||||
* a firmware update. The hook function FileFirmwareUpdateLogHook() will be called each
|
||||
* time a new string formatted log entry is available. This could be used during testing
|
||||
* by outputting the string on UART or to create a log file on the file system itself.
|
||||
*
|
||||
* Set BOOT_FILE_ERROR_HOOK_ENABLE to 1 if you would like to be informed in case an error
|
||||
* occurs during the firmware update. This could for example be used to turn on an error
|
||||
* LED to inform the user that something went wrong. Inspecting the log messages provides
|
||||
* additional information on the error cause.
|
||||
*
|
||||
* Set BOOT_FILE_STARTED_HOOK_ENABLE to 1 if you would like to be informed when a new
|
||||
* firmware update is started by the bootloader.
|
||||
*
|
||||
* Set BOOT_FILE_COMPLETED_HOOK_ENABLE to 1 if you would like to be informed when a
|
||||
* firmware update is completed by the bootloader.
|
||||
*/
|
||||
/** \brief Enable/disable support for firmware updates from a locally attached storage.*/
|
||||
#define BOOT_FILE_SYS_ENABLE (1)
|
||||
/** \brief Enable/disable logging messages during firmware updates. */
|
||||
#define BOOT_FILE_LOGGING_ENABLE (1)
|
||||
/** \brief Enable/disable a hook function that is called upon detection of an error. */
|
||||
#define BOOT_FILE_ERROR_HOOK_ENABLE (1)
|
||||
/** \brief Enable/disable a hook function that is called at the start of the update. */
|
||||
#define BOOT_FILE_STARTED_HOOK_ENABLE (1)
|
||||
/** \brief Enable/disable a hook function that is called at the end of the update. */
|
||||
#define BOOT_FILE_COMPLETED_HOOK_ENABLE (1)
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* B A C K D O O R E N T R Y C O N F I G U R A T I O N
|
||||
****************************************************************************************/
|
||||
|
|
|
@ -53,7 +53,22 @@ static const tFlashSector flashLayout[] =
|
|||
/* { 0x08006800, 0x00800 }, flash sector 13 - 2kb (reserved for bootloader)*/
|
||||
/* { 0x08007000, 0x00800 }, flash sector 14 - 2kb (reserved for bootloader)*/
|
||||
/* { 0x08007800, 0x00800 }, flash sector 15 - 2kb (reserved for bootloader)*/
|
||||
{ 0x08008000, 0x08000 }, /* flash sectors 16 to 31 - 32kb */
|
||||
/* { 0x08008000, 0x00800 }, flash sector 16 - 2kb (reserved for bootloader)*/
|
||||
/* { 0x08008800, 0x00800 }, flash sector 17 - 2kb (reserved for bootloader)*/
|
||||
/* { 0x08009000, 0x00800 }, flash sector 18 - 2kb (reserved for bootloader)*/
|
||||
/* { 0x08009800, 0x00800 }, flash sector 19 - 2kb (reserved for bootloader)*/
|
||||
{ 0x0800A000, 0x00800 }, /* flash sector 20 - 2kb */
|
||||
{ 0x0800A800, 0x00800 }, /* flash sector 21 - 2kb */
|
||||
{ 0x0800B000, 0x00800 }, /* flash sector 22 - 2kb */
|
||||
{ 0x0800B800, 0x00800 }, /* flash sector 23 - 2kb */
|
||||
{ 0x0800C000, 0x00800 }, /* flash sector 24 - 2kb */
|
||||
{ 0x0800C800, 0x00800 }, /* flash sector 25 - 2kb */
|
||||
{ 0x0800D000, 0x00800 }, /* flash sector 26 - 2kb */
|
||||
{ 0x0800D800, 0x00800 }, /* flash sector 27 - 2kb */
|
||||
{ 0x0800E000, 0x00800 }, /* flash sector 28 - 2kb */
|
||||
{ 0x0800E800, 0x00800 }, /* flash sector 29 - 2kb */
|
||||
{ 0x0800F000, 0x00800 }, /* flash sector 30 - 2kb */
|
||||
{ 0x0800F800, 0x00800 }, /* flash sector 31 - 2kb */
|
||||
{ 0x08010000, 0x08000 }, /* flash sectors 32 to 47 - 32kb */
|
||||
{ 0x08018000, 0x08000 }, /* flash sectors 48 to 63 - 32kb */
|
||||
{ 0x08020000, 0x08000 }, /* flash sectors 64 to 79 - 32kb */
|
||||
|
|
|
@ -300,6 +300,168 @@ blt_bool NvmWriteChecksumHook(void)
|
|||
#endif /* BOOT_NVM_CHECKSUM_HOOKS_ENABLE > 0 */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* F I L E S Y S T E M I N T E R F A C E H O O K F U N C T I O N S
|
||||
****************************************************************************************/
|
||||
|
||||
#if (BOOT_FILE_SYS_ENABLE > 0)
|
||||
|
||||
/****************************************************************************************
|
||||
* Constant data declarations
|
||||
****************************************************************************************/
|
||||
/** \brief Firmware filename. */
|
||||
static const blt_char firmwareFilename[] = "/demoprog_olimexino_stm32f3.srec";
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local data declarations
|
||||
****************************************************************************************/
|
||||
#if (BOOT_FILE_LOGGING_ENABLE > 0)
|
||||
/** \brief Data structure for grouping log-file related information. */
|
||||
static struct
|
||||
{
|
||||
FIL handle; /**< FatFS handle to the log-file. */
|
||||
blt_bool canUse; /**< Flag to indicate if the log-file can be used. */
|
||||
} logfile;
|
||||
#endif
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Callback that gets called to check whether a firmware update from
|
||||
** local file storage should be started. This could for example be when
|
||||
** a switch is pressed, when a certain file is found on the local file
|
||||
** storage, etc.
|
||||
** \return BLT_TRUE if a firmware update is requested, BLT_FALSE otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
blt_bool FileIsFirmwareUpdateRequestedHook(void)
|
||||
{
|
||||
FILINFO fileInfoObject = { 0 }; /* needs to be zeroed according to f_stat docs */;
|
||||
|
||||
/* Current example implementation looks for a predetermined firmware file on the
|
||||
* SD-card. If the SD-card is accessible and the firmware file was found the firmware
|
||||
* update is started. When successfully completed, the firmware file is deleted.
|
||||
* During the firmware update, progress information is written to a file called
|
||||
* bootlog.txt and additionally outputted on UART @57600 bps for debugging purposes.
|
||||
*/
|
||||
/* check if firmware file is present and SD-card is accessible */
|
||||
if (f_stat(firmwareFilename, &fileInfoObject) == FR_OK)
|
||||
{
|
||||
/* check if the filesize is valid and that it is not a directory */
|
||||
if ( (fileInfoObject.fsize > 0) && (!(fileInfoObject.fattrib & AM_DIR)) )
|
||||
{
|
||||
/* all conditions are met to start a firmware update from local file storage */
|
||||
return BLT_TRUE;
|
||||
}
|
||||
}
|
||||
/* still here so no firmware update request is pending */
|
||||
return BLT_FALSE;
|
||||
} /*** end of FileIsFirmwareUpdateRequestedHook ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Callback to obtain the filename of the firmware file that should be
|
||||
** used during the firmware update from the local file storage. This
|
||||
** hook function is called at the beginning of the firmware update from
|
||||
** local storage sequence.
|
||||
** \return valid firmware filename with full path or BLT_NULL.
|
||||
**
|
||||
****************************************************************************************/
|
||||
const blt_char *FileGetFirmwareFilenameHook(void)
|
||||
{
|
||||
return firmwareFilename;
|
||||
} /*** end of FileGetFirmwareFilenameHook ***/
|
||||
|
||||
|
||||
#if (BOOT_FILE_STARTED_HOOK_ENABLE > 0)
|
||||
/************************************************************************************//**
|
||||
** \brief Callback that gets called to inform the application that a firmware
|
||||
** update from local storage just started.
|
||||
** \return none.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void FileFirmwareUpdateStartedHook(void)
|
||||
{
|
||||
#if (BOOT_FILE_LOGGING_ENABLE > 0)
|
||||
/* create/overwrite the logfile */
|
||||
logfile.canUse = BLT_FALSE;
|
||||
if (f_open(&logfile.handle, "/bootlog.txt", FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)
|
||||
{
|
||||
logfile.canUse = BLT_TRUE;
|
||||
}
|
||||
#endif
|
||||
} /*** end of FileFirmwareUpdateStartedHook ***/
|
||||
#endif /* BOOT_FILE_STARTED_HOOK_ENABLE > 0 */
|
||||
|
||||
|
||||
#if (BOOT_FILE_COMPLETED_HOOK_ENABLE > 0)
|
||||
/************************************************************************************//**
|
||||
** \brief Callback that gets called to inform the application that a firmware
|
||||
** update was successfully completed.
|
||||
** \return none.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void FileFirmwareUpdateCompletedHook(void)
|
||||
{
|
||||
#if (BOOT_FILE_LOGGING_ENABLE > 0)
|
||||
/* close the log file */
|
||||
if (logfile.canUse == BLT_TRUE)
|
||||
{
|
||||
f_close(&logfile.handle);
|
||||
}
|
||||
/* now delete the firmware file from the disk since the update was successful */
|
||||
f_unlink(firmwareFilename);
|
||||
#endif
|
||||
} /*** end of FileFirmwareUpdateCompletedHook ***/
|
||||
#endif /* BOOT_FILE_COMPLETED_HOOK_ENABLE > 0 */
|
||||
|
||||
|
||||
#if (BOOT_FILE_ERROR_HOOK_ENABLE > 0)
|
||||
/************************************************************************************//**
|
||||
** \brief Callback that gets called in case an error occurred during a firmware
|
||||
** update. Refer to <file.h> for a list of available error codes.
|
||||
** \return none.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void FileFirmwareUpdateErrorHook(blt_int8u error_code)
|
||||
{
|
||||
#if (BOOT_FILE_LOGGING_ENABLE > 0)
|
||||
/* error detected which stops the firmware update, so close the log file */
|
||||
if (logfile.canUse == BLT_TRUE)
|
||||
{
|
||||
f_close(&logfile.handle);
|
||||
}
|
||||
#endif
|
||||
} /*** end of FileFirmwareUpdateErrorHook ***/
|
||||
#endif /* BOOT_FILE_ERROR_HOOK_ENABLE > 0 */
|
||||
|
||||
|
||||
#if (BOOT_FILE_LOGGING_ENABLE > 0)
|
||||
/************************************************************************************//**
|
||||
** \brief Callback that gets called each time new log information becomes
|
||||
** available during a firmware update.
|
||||
** \param info_string Pointer to a character array with the log entry info.
|
||||
** \return none.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void FileFirmwareUpdateLogHook(blt_char *info_string)
|
||||
{
|
||||
/* write the string to the log file */
|
||||
if (logfile.canUse == BLT_TRUE)
|
||||
{
|
||||
if (f_puts(info_string, &logfile.handle) < 0)
|
||||
{
|
||||
logfile.canUse = BLT_FALSE;
|
||||
f_close(&logfile.handle);
|
||||
}
|
||||
}
|
||||
} /*** end of FileFirmwareUpdateLogHook ***/
|
||||
#endif /* BOOT_FILE_LOGGING_ENABLE > 0 */
|
||||
|
||||
|
||||
#endif /* BOOT_FILE_SYS_ENABLE > 0 */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* S E E D / K E Y S E C U R I T Y H O O K F U N C T I O N S
|
||||
****************************************************************************************/
|
||||
|
|
|
@ -11,29 +11,35 @@ CAN.IPParameters=CalculateTimeQuantum,CalculateTimeBit,CalculateBaudRate,BS1,BS2
|
|||
CAN.NART=ENABLE
|
||||
CAN.Prescaler=8
|
||||
File.Version=6
|
||||
GPIO.groupedBy=Group By Peripherals
|
||||
KeepUserPlacement=false
|
||||
Mcu.CPN=STM32F303RCT6
|
||||
Mcu.Family=STM32F3
|
||||
Mcu.IP0=CAN
|
||||
Mcu.IP1=NVIC
|
||||
Mcu.IP2=RCC
|
||||
Mcu.IP3=USART3
|
||||
Mcu.IP4=USB
|
||||
Mcu.IPNb=5
|
||||
Mcu.IP3=SPI2
|
||||
Mcu.IP4=USART3
|
||||
Mcu.IP5=USB
|
||||
Mcu.IPNb=6
|
||||
Mcu.Name=STM32F303R(B-C)Tx
|
||||
Mcu.Package=LQFP64
|
||||
Mcu.Pin0=PF0-OSC_IN
|
||||
Mcu.Pin1=PF1-OSC_OUT
|
||||
Mcu.Pin10=PB9
|
||||
Mcu.Pin10=PA12
|
||||
Mcu.Pin11=PC12
|
||||
Mcu.Pin12=PD2
|
||||
Mcu.Pin13=PB8
|
||||
Mcu.Pin14=PB9
|
||||
Mcu.Pin2=PA0
|
||||
Mcu.Pin3=PA5
|
||||
Mcu.Pin4=PB10
|
||||
Mcu.Pin5=PB11
|
||||
Mcu.Pin6=PA11
|
||||
Mcu.Pin7=PA12
|
||||
Mcu.Pin8=PC12
|
||||
Mcu.Pin9=PB8
|
||||
Mcu.PinsNb=11
|
||||
Mcu.Pin6=PB13
|
||||
Mcu.Pin7=PB14
|
||||
Mcu.Pin8=PB15
|
||||
Mcu.Pin9=PA11
|
||||
Mcu.PinsNb=15
|
||||
Mcu.ThirdPartyNb=0
|
||||
Mcu.UserConstants=
|
||||
Mcu.UserName=STM32F303RCTx
|
||||
|
@ -66,6 +72,15 @@ PB10.Signal=USART3_TX
|
|||
PB11.Locked=true
|
||||
PB11.Mode=Asynchronous
|
||||
PB11.Signal=USART3_RX
|
||||
PB13.Locked=true
|
||||
PB13.Mode=Full_Duplex_Master
|
||||
PB13.Signal=SPI2_SCK
|
||||
PB14.Locked=true
|
||||
PB14.Mode=Full_Duplex_Master
|
||||
PB14.Signal=SPI2_MISO
|
||||
PB15.Locked=true
|
||||
PB15.Mode=Full_Duplex_Master
|
||||
PB15.Signal=SPI2_MOSI
|
||||
PB8.Locked=true
|
||||
PB8.Mode=CAN_Activate
|
||||
PB8.Signal=CAN_RX
|
||||
|
@ -75,6 +90,10 @@ PC12.GPIOParameters=PinState
|
|||
PC12.Locked=true
|
||||
PC12.PinState=GPIO_PIN_SET
|
||||
PC12.Signal=GPIO_Output
|
||||
PD2.GPIOParameters=GPIO_Speed
|
||||
PD2.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
||||
PD2.Locked=true
|
||||
PD2.Signal=GPIO_Output
|
||||
PF0-OSC_IN.Mode=HSE-External-Oscillator
|
||||
PF0-OSC_IN.Signal=RCC_OSC_IN
|
||||
PF1-OSC_OUT.Mode=HSE-External-Oscillator
|
||||
|
@ -107,7 +126,7 @@ ProjectManager.StackSize=0x1000
|
|||
ProjectManager.TargetToolchain=STM32CubeIDE
|
||||
ProjectManager.ToolChainLocation=
|
||||
ProjectManager.UnderRoot=true
|
||||
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_CAN_Init-CAN-true-HAL-false,4-MX_USART3_UART_Init-USART3-false-LL-true,5-MX_USB_PCD_Init-USB-true-HAL-false
|
||||
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_CAN_Init-CAN-true-HAL-false,4-MX_USART3_UART_Init-USART3-false-LL-true,5-MX_USB_PCD_Init-USB-true-HAL-false,6-MX_SPI2_Init-SPI2-true-LL-false
|
||||
RCC.ADC12outputFreq_Value=72000000
|
||||
RCC.ADC34outputFreq_Value=72000000
|
||||
RCC.AHBFreq_Value=72000000
|
||||
|
@ -149,6 +168,14 @@ RCC.USART2Freq_Value=36000000
|
|||
RCC.USART3Freq_Value=36000000
|
||||
RCC.USBFreq_Value=48000000
|
||||
RCC.VCOOutput2Freq_Value=8000000
|
||||
SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_2
|
||||
SPI2.CalculateBaudRate=18.0 MBits/s
|
||||
SPI2.DataSize=SPI_DATASIZE_8BIT
|
||||
SPI2.Direction=SPI_DIRECTION_2LINES
|
||||
SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,NSSPMode,BaudRatePrescaler
|
||||
SPI2.Mode=SPI_MODE_MASTER
|
||||
SPI2.NSSPMode=SPI_NSS_PULSE_DISABLE
|
||||
SPI2.VirtualType=VM_MASTER
|
||||
USART3.BaudRate=57600
|
||||
USART3.IPParameters=VirtualMode-Asynchronous,BaudRate
|
||||
USART3.VirtualMode-Asynchronous=VM_ASYNC
|
||||
|
|
|
@ -36,6 +36,7 @@ extern "C" {
|
|||
#include "stm32f3xx_ll_utils.h"
|
||||
#include "stm32f3xx_ll_pwr.h"
|
||||
#include "stm32f3xx_ll_dma.h"
|
||||
#include "stm32f3xx_ll_spi.h"
|
||||
#include "stm32f3xx_ll_usart.h"
|
||||
#include "stm32f3xx_ll_gpio.h"
|
||||
|
||||
|
@ -63,6 +64,7 @@ extern "C" {
|
|||
void Error_Handler(void);
|
||||
void MX_CAN_Init(void);
|
||||
void MX_USB_PCD_Init(void);
|
||||
void MX_SPI2_Init(void);
|
||||
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
|
|
|
@ -192,6 +192,64 @@ void MX_CAN_Init(void)
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI2 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void MX_SPI2_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN SPI2_Init 0 */
|
||||
/* Note that this function is generated but not actually used. The FatFS port handles
|
||||
* the SPI initialization.
|
||||
*/
|
||||
/* USER CODE END SPI2_Init 0 */
|
||||
|
||||
LL_SPI_InitTypeDef SPI_InitStruct = {0};
|
||||
|
||||
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
|
||||
/* Peripheral clock enable */
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
|
||||
/**SPI2 GPIO Configuration
|
||||
PB13 ------> SPI2_SCK
|
||||
PB14 ------> SPI2_MISO
|
||||
PB15 ------> SPI2_MOSI
|
||||
*/
|
||||
GPIO_InitStruct.Pin = LL_GPIO_PIN_13|LL_GPIO_PIN_14|LL_GPIO_PIN_15;
|
||||
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
|
||||
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
||||
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
|
||||
GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
|
||||
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN SPI2_Init 1 */
|
||||
|
||||
/* USER CODE END SPI2_Init 1 */
|
||||
/* SPI2 parameter configuration*/
|
||||
SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
|
||||
SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
|
||||
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
|
||||
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
|
||||
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
|
||||
SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
|
||||
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;
|
||||
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
|
||||
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
|
||||
SPI_InitStruct.CRCPoly = 7;
|
||||
LL_SPI_Init(SPI2, &SPI_InitStruct);
|
||||
LL_SPI_SetStandard(SPI2, LL_SPI_PROTOCOL_MOTOROLA);
|
||||
LL_SPI_DisableNSSPulseMgt(SPI2);
|
||||
/* USER CODE BEGIN SPI2_Init 2 */
|
||||
|
||||
/* USER CODE END SPI2_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USART3 Initialization Function
|
||||
* @param None
|
||||
|
@ -293,10 +351,14 @@ static void MX_GPIO_Init(void)
|
|||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC);
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOD);
|
||||
|
||||
/**/
|
||||
LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_5);
|
||||
|
||||
/**/
|
||||
LL_GPIO_ResetOutputPin(GPIOD, LL_GPIO_PIN_2);
|
||||
|
||||
/**/
|
||||
LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_12);
|
||||
|
||||
|
@ -322,6 +384,14 @@ static void MX_GPIO_Init(void)
|
|||
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
|
||||
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
|
||||
/**/
|
||||
GPIO_InitStruct.Pin = LL_GPIO_PIN_2;
|
||||
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
|
||||
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
||||
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
|
||||
LL_GPIO_Init(GPIOD, &GPIO_InitStruct);
|
||||
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 4 */
|
||||
|
|
|
@ -235,13 +235,17 @@ void HAL_MspDeInit(void)
|
|||
LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_5);
|
||||
|
||||
/* Deinit used GPIOs, except GPIOC to make sure USB DISC (PC12) stays high. */
|
||||
LL_GPIO_DeInit(GPIOD);
|
||||
LL_GPIO_DeInit(GPIOB);
|
||||
LL_GPIO_DeInit(GPIOA);
|
||||
|
||||
/* UART clock disable. */
|
||||
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_USART3);
|
||||
/* SPI clock disable. */
|
||||
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
|
||||
/* GPIO ports clock disable, except GPIOC to make sure USB DISC (PC12) stays high. */
|
||||
LL_AHB1_GRP1_DisableClock(LL_AHB1_GRP1_PERIPH_GPIOD);
|
||||
LL_AHB1_GRP1_DisableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
|
||||
LL_AHB1_GRP1_DisableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,640 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f3xx_ll_spi.c
|
||||
* @author MCD Application Team
|
||||
* @brief SPI LL module driver.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f3xx_ll_spi.h"
|
||||
#include "stm32f3xx_ll_bus.h"
|
||||
#include "stm32f3xx_ll_rcc.h"
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
/** @addtogroup STM32F3xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (SPI1) || defined (SPI2) || defined (SPI3) || defined (SPI4)
|
||||
|
||||
/** @addtogroup SPI_LL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/** @defgroup SPI_LL_Private_Constants SPI Private Constants
|
||||
* @{
|
||||
*/
|
||||
/* SPI registers Masks */
|
||||
#define SPI_CR1_CLEAR_MASK (SPI_CR1_CPHA | SPI_CR1_CPOL | SPI_CR1_MSTR | \
|
||||
SPI_CR1_BR | SPI_CR1_LSBFIRST | SPI_CR1_SSI | \
|
||||
SPI_CR1_SSM | SPI_CR1_RXONLY | SPI_CR1_CRCL | \
|
||||
SPI_CR1_CRCNEXT | SPI_CR1_CRCEN | SPI_CR1_BIDIOE | \
|
||||
SPI_CR1_BIDIMODE)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @defgroup SPI_LL_Private_Macros SPI Private Macros
|
||||
* @{
|
||||
*/
|
||||
#define IS_LL_SPI_TRANSFER_DIRECTION(__VALUE__) (((__VALUE__) == LL_SPI_FULL_DUPLEX) \
|
||||
|| ((__VALUE__) == LL_SPI_SIMPLEX_RX) \
|
||||
|| ((__VALUE__) == LL_SPI_HALF_DUPLEX_RX) \
|
||||
|| ((__VALUE__) == LL_SPI_HALF_DUPLEX_TX))
|
||||
|
||||
#define IS_LL_SPI_MODE(__VALUE__) (((__VALUE__) == LL_SPI_MODE_MASTER) \
|
||||
|| ((__VALUE__) == LL_SPI_MODE_SLAVE))
|
||||
|
||||
#define IS_LL_SPI_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_SPI_DATAWIDTH_4BIT) \
|
||||
|| ((__VALUE__) == LL_SPI_DATAWIDTH_5BIT) \
|
||||
|| ((__VALUE__) == LL_SPI_DATAWIDTH_6BIT) \
|
||||
|| ((__VALUE__) == LL_SPI_DATAWIDTH_7BIT) \
|
||||
|| ((__VALUE__) == LL_SPI_DATAWIDTH_8BIT) \
|
||||
|| ((__VALUE__) == LL_SPI_DATAWIDTH_9BIT) \
|
||||
|| ((__VALUE__) == LL_SPI_DATAWIDTH_10BIT) \
|
||||
|| ((__VALUE__) == LL_SPI_DATAWIDTH_11BIT) \
|
||||
|| ((__VALUE__) == LL_SPI_DATAWIDTH_12BIT) \
|
||||
|| ((__VALUE__) == LL_SPI_DATAWIDTH_13BIT) \
|
||||
|| ((__VALUE__) == LL_SPI_DATAWIDTH_14BIT) \
|
||||
|| ((__VALUE__) == LL_SPI_DATAWIDTH_15BIT) \
|
||||
|| ((__VALUE__) == LL_SPI_DATAWIDTH_16BIT))
|
||||
|
||||
#define IS_LL_SPI_POLARITY(__VALUE__) (((__VALUE__) == LL_SPI_POLARITY_LOW) \
|
||||
|| ((__VALUE__) == LL_SPI_POLARITY_HIGH))
|
||||
|
||||
#define IS_LL_SPI_PHASE(__VALUE__) (((__VALUE__) == LL_SPI_PHASE_1EDGE) \
|
||||
|| ((__VALUE__) == LL_SPI_PHASE_2EDGE))
|
||||
|
||||
#define IS_LL_SPI_NSS(__VALUE__) (((__VALUE__) == LL_SPI_NSS_SOFT) \
|
||||
|| ((__VALUE__) == LL_SPI_NSS_HARD_INPUT) \
|
||||
|| ((__VALUE__) == LL_SPI_NSS_HARD_OUTPUT))
|
||||
|
||||
#define IS_LL_SPI_BAUDRATE(__VALUE__) (((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV2) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV4) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV8) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV16) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV32) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV64) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV128) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV256))
|
||||
|
||||
#define IS_LL_SPI_BITORDER(__VALUE__) (((__VALUE__) == LL_SPI_LSB_FIRST) \
|
||||
|| ((__VALUE__) == LL_SPI_MSB_FIRST))
|
||||
|
||||
#define IS_LL_SPI_CRCCALCULATION(__VALUE__) (((__VALUE__) == LL_SPI_CRCCALCULATION_ENABLE) \
|
||||
|| ((__VALUE__) == LL_SPI_CRCCALCULATION_DISABLE))
|
||||
|
||||
#define IS_LL_SPI_CRC_POLYNOMIAL(__VALUE__) ((__VALUE__) >= 0x1U)
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup SPI_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup SPI_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize the SPI registers to their default reset values.
|
||||
* @param SPIx SPI Instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: SPI registers are de-initialized
|
||||
* - ERROR: SPI registers are not de-initialized
|
||||
*/
|
||||
ErrorStatus LL_SPI_DeInit(SPI_TypeDef *SPIx)
|
||||
{
|
||||
ErrorStatus status = ERROR;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SPI_ALL_INSTANCE(SPIx));
|
||||
|
||||
#if defined(SPI1)
|
||||
if (SPIx == SPI1)
|
||||
{
|
||||
/* Force reset of SPI clock */
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
|
||||
/* Release reset of SPI clock */
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
#endif /* SPI1 */
|
||||
#if defined(SPI2)
|
||||
if (SPIx == SPI2)
|
||||
{
|
||||
/* Force reset of SPI clock */
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
|
||||
/* Release reset of SPI clock */
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
#endif /* SPI2 */
|
||||
#if defined(SPI3)
|
||||
if (SPIx == SPI3)
|
||||
{
|
||||
/* Force reset of SPI clock */
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI3);
|
||||
|
||||
/* Release reset of SPI clock */
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI3);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
#endif /* SPI3 */
|
||||
#if defined(SPI4)
|
||||
if (SPIx == SPI4)
|
||||
{
|
||||
/* Force reset of SPI clock */
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI4);
|
||||
|
||||
/* Release reset of SPI clock */
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI4);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
#endif /* SPI4 */
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the SPI registers according to the specified parameters in SPI_InitStruct.
|
||||
* @note As some bits in SPI configuration registers can only be written when the SPI is disabled (SPI_CR1_SPE bit =0),
|
||||
* SPI peripheral should be in disabled state prior calling this function. Otherwise, ERROR result will be returned.
|
||||
* @param SPIx SPI Instance
|
||||
* @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value. (Return always SUCCESS)
|
||||
*/
|
||||
ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct)
|
||||
{
|
||||
ErrorStatus status = ERROR;
|
||||
|
||||
/* Check the SPI Instance SPIx*/
|
||||
assert_param(IS_SPI_ALL_INSTANCE(SPIx));
|
||||
|
||||
/* Check the SPI parameters from SPI_InitStruct*/
|
||||
assert_param(IS_LL_SPI_TRANSFER_DIRECTION(SPI_InitStruct->TransferDirection));
|
||||
assert_param(IS_LL_SPI_MODE(SPI_InitStruct->Mode));
|
||||
assert_param(IS_LL_SPI_DATAWIDTH(SPI_InitStruct->DataWidth));
|
||||
assert_param(IS_LL_SPI_POLARITY(SPI_InitStruct->ClockPolarity));
|
||||
assert_param(IS_LL_SPI_PHASE(SPI_InitStruct->ClockPhase));
|
||||
assert_param(IS_LL_SPI_NSS(SPI_InitStruct->NSS));
|
||||
assert_param(IS_LL_SPI_BAUDRATE(SPI_InitStruct->BaudRate));
|
||||
assert_param(IS_LL_SPI_BITORDER(SPI_InitStruct->BitOrder));
|
||||
assert_param(IS_LL_SPI_CRCCALCULATION(SPI_InitStruct->CRCCalculation));
|
||||
|
||||
if (LL_SPI_IsEnabled(SPIx) == 0x00000000U)
|
||||
{
|
||||
/*---------------------------- SPIx CR1 Configuration ------------------------
|
||||
* Configure SPIx CR1 with parameters:
|
||||
* - TransferDirection: SPI_CR1_BIDIMODE, SPI_CR1_BIDIOE and SPI_CR1_RXONLY bits
|
||||
* - Master/Slave Mode: SPI_CR1_MSTR bit
|
||||
* - ClockPolarity: SPI_CR1_CPOL bit
|
||||
* - ClockPhase: SPI_CR1_CPHA bit
|
||||
* - NSS management: SPI_CR1_SSM bit
|
||||
* - BaudRate prescaler: SPI_CR1_BR[2:0] bits
|
||||
* - BitOrder: SPI_CR1_LSBFIRST bit
|
||||
* - CRCCalculation: SPI_CR1_CRCEN bit
|
||||
*/
|
||||
MODIFY_REG(SPIx->CR1,
|
||||
SPI_CR1_CLEAR_MASK,
|
||||
SPI_InitStruct->TransferDirection | SPI_InitStruct->Mode |
|
||||
SPI_InitStruct->ClockPolarity | SPI_InitStruct->ClockPhase |
|
||||
SPI_InitStruct->NSS | SPI_InitStruct->BaudRate |
|
||||
SPI_InitStruct->BitOrder | SPI_InitStruct->CRCCalculation);
|
||||
|
||||
/*---------------------------- SPIx CR2 Configuration ------------------------
|
||||
* Configure SPIx CR2 with parameters:
|
||||
* - DataWidth: DS[3:0] bits
|
||||
* - NSS management: SSOE bit
|
||||
*/
|
||||
MODIFY_REG(SPIx->CR2,
|
||||
SPI_CR2_DS | SPI_CR2_SSOE,
|
||||
SPI_InitStruct->DataWidth | (SPI_InitStruct->NSS >> 16U));
|
||||
|
||||
/* Set Rx FIFO to Quarter (1 Byte) in case of 8 Bits mode. No DataPacking by default */
|
||||
if (SPI_InitStruct->DataWidth < LL_SPI_DATAWIDTH_9BIT)
|
||||
{
|
||||
LL_SPI_SetRxFIFOThreshold(SPIx, LL_SPI_RX_FIFO_TH_QUARTER);
|
||||
}
|
||||
|
||||
/*---------------------------- SPIx CRCPR Configuration ----------------------
|
||||
* Configure SPIx CRCPR with parameters:
|
||||
* - CRCPoly: CRCPOLY[15:0] bits
|
||||
*/
|
||||
if (SPI_InitStruct->CRCCalculation == LL_SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
assert_param(IS_LL_SPI_CRC_POLYNOMIAL(SPI_InitStruct->CRCPoly));
|
||||
LL_SPI_SetCRCPolynomial(SPIx, SPI_InitStruct->CRCPoly);
|
||||
}
|
||||
status = SUCCESS;
|
||||
}
|
||||
|
||||
#if defined (SPI_I2S_SUPPORT)
|
||||
/* Activate the SPI mode (Reset I2SMOD bit in I2SCFGR register) */
|
||||
CLEAR_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SMOD);
|
||||
#endif /* SPI_I2S_SUPPORT */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_SPI_InitTypeDef field to default value.
|
||||
* @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct)
|
||||
{
|
||||
/* Set SPI_InitStruct fields to default values */
|
||||
SPI_InitStruct->TransferDirection = LL_SPI_FULL_DUPLEX;
|
||||
SPI_InitStruct->Mode = LL_SPI_MODE_SLAVE;
|
||||
SPI_InitStruct->DataWidth = LL_SPI_DATAWIDTH_8BIT;
|
||||
SPI_InitStruct->ClockPolarity = LL_SPI_POLARITY_LOW;
|
||||
SPI_InitStruct->ClockPhase = LL_SPI_PHASE_1EDGE;
|
||||
SPI_InitStruct->NSS = LL_SPI_NSS_HARD_INPUT;
|
||||
SPI_InitStruct->BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;
|
||||
SPI_InitStruct->BitOrder = LL_SPI_MSB_FIRST;
|
||||
SPI_InitStruct->CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
|
||||
SPI_InitStruct->CRCPoly = 7U;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#if defined(SPI_I2S_SUPPORT)
|
||||
/** @addtogroup I2S_LL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/** @defgroup I2S_LL_Private_Constants I2S Private Constants
|
||||
* @{
|
||||
*/
|
||||
/* I2S registers Masks */
|
||||
#define I2S_I2SCFGR_CLEAR_MASK (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | \
|
||||
SPI_I2SCFGR_CKPOL | SPI_I2SCFGR_I2SSTD | \
|
||||
SPI_I2SCFGR_I2SCFG | SPI_I2SCFGR_I2SMOD )
|
||||
|
||||
#define I2S_I2SPR_CLEAR_MASK 0x0002U
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @defgroup I2S_LL_Private_Macros I2S Private Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define IS_LL_I2S_DATAFORMAT(__VALUE__) (((__VALUE__) == LL_I2S_DATAFORMAT_16B) \
|
||||
|| ((__VALUE__) == LL_I2S_DATAFORMAT_16B_EXTENDED) \
|
||||
|| ((__VALUE__) == LL_I2S_DATAFORMAT_24B) \
|
||||
|| ((__VALUE__) == LL_I2S_DATAFORMAT_32B))
|
||||
|
||||
#define IS_LL_I2S_CPOL(__VALUE__) (((__VALUE__) == LL_I2S_POLARITY_LOW) \
|
||||
|| ((__VALUE__) == LL_I2S_POLARITY_HIGH))
|
||||
|
||||
#define IS_LL_I2S_STANDARD(__VALUE__) (((__VALUE__) == LL_I2S_STANDARD_PHILIPS) \
|
||||
|| ((__VALUE__) == LL_I2S_STANDARD_MSB) \
|
||||
|| ((__VALUE__) == LL_I2S_STANDARD_LSB) \
|
||||
|| ((__VALUE__) == LL_I2S_STANDARD_PCM_SHORT) \
|
||||
|| ((__VALUE__) == LL_I2S_STANDARD_PCM_LONG))
|
||||
|
||||
#define IS_LL_I2S_MODE(__VALUE__) (((__VALUE__) == LL_I2S_MODE_SLAVE_TX) \
|
||||
|| ((__VALUE__) == LL_I2S_MODE_SLAVE_RX) \
|
||||
|| ((__VALUE__) == LL_I2S_MODE_MASTER_TX) \
|
||||
|| ((__VALUE__) == LL_I2S_MODE_MASTER_RX))
|
||||
|
||||
#define IS_LL_I2S_MCLK_OUTPUT(__VALUE__) (((__VALUE__) == LL_I2S_MCLK_OUTPUT_ENABLE) \
|
||||
|| ((__VALUE__) == LL_I2S_MCLK_OUTPUT_DISABLE))
|
||||
|
||||
#define IS_LL_I2S_AUDIO_FREQ(__VALUE__) ((((__VALUE__) >= LL_I2S_AUDIOFREQ_8K) \
|
||||
&& ((__VALUE__) <= LL_I2S_AUDIOFREQ_192K)) \
|
||||
|| ((__VALUE__) == LL_I2S_AUDIOFREQ_DEFAULT))
|
||||
|
||||
#define IS_LL_I2S_PRESCALER_LINEAR(__VALUE__) ((__VALUE__) >= 0x2U)
|
||||
|
||||
#define IS_LL_I2S_PRESCALER_PARITY(__VALUE__) (((__VALUE__) == LL_I2S_PRESCALER_PARITY_EVEN) \
|
||||
|| ((__VALUE__) == LL_I2S_PRESCALER_PARITY_ODD))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup I2S_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup I2S_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize the SPI/I2S registers to their default reset values.
|
||||
* @param SPIx SPI Instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: SPI registers are de-initialized
|
||||
* - ERROR: SPI registers are not de-initialized
|
||||
*/
|
||||
ErrorStatus LL_I2S_DeInit(SPI_TypeDef *SPIx)
|
||||
{
|
||||
return LL_SPI_DeInit(SPIx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the SPI/I2S registers according to the specified parameters in I2S_InitStruct.
|
||||
* @note As some bits in SPI configuration registers can only be written when the SPI is disabled (SPI_CR1_SPE bit =0),
|
||||
* SPI peripheral should be in disabled state prior calling this function. Otherwise, ERROR result will be returned.
|
||||
* @param SPIx SPI Instance
|
||||
* @param I2S_InitStruct pointer to a @ref LL_I2S_InitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: SPI registers are Initialized
|
||||
* - ERROR: SPI registers are not Initialized
|
||||
*/
|
||||
ErrorStatus LL_I2S_Init(SPI_TypeDef *SPIx, LL_I2S_InitTypeDef *I2S_InitStruct)
|
||||
{
|
||||
uint32_t i2sdiv = 2U;
|
||||
uint32_t i2sodd = 0U;
|
||||
uint32_t packetlength = 1U;
|
||||
uint32_t tmp;
|
||||
#if !defined (SPI_I2S_FULLDUPLEX_SUPPORT)
|
||||
LL_RCC_ClocksTypeDef rcc_clocks;
|
||||
#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */
|
||||
uint32_t sourceclock;
|
||||
ErrorStatus status = ERROR;
|
||||
|
||||
/* Check the I2S parameters */
|
||||
assert_param(IS_I2S_ALL_INSTANCE(SPIx));
|
||||
assert_param(IS_LL_I2S_MODE(I2S_InitStruct->Mode));
|
||||
assert_param(IS_LL_I2S_STANDARD(I2S_InitStruct->Standard));
|
||||
assert_param(IS_LL_I2S_DATAFORMAT(I2S_InitStruct->DataFormat));
|
||||
assert_param(IS_LL_I2S_MCLK_OUTPUT(I2S_InitStruct->MCLKOutput));
|
||||
assert_param(IS_LL_I2S_AUDIO_FREQ(I2S_InitStruct->AudioFreq));
|
||||
assert_param(IS_LL_I2S_CPOL(I2S_InitStruct->ClockPolarity));
|
||||
|
||||
if (LL_I2S_IsEnabled(SPIx) == 0x00000000U)
|
||||
{
|
||||
/*---------------------------- SPIx I2SCFGR Configuration --------------------
|
||||
* Configure SPIx I2SCFGR with parameters:
|
||||
* - Mode: SPI_I2SCFGR_I2SCFG[1:0] bit
|
||||
* - Standard: SPI_I2SCFGR_I2SSTD[1:0] and SPI_I2SCFGR_PCMSYNC bits
|
||||
* - DataFormat: SPI_I2SCFGR_CHLEN and SPI_I2SCFGR_DATLEN bits
|
||||
* - ClockPolarity: SPI_I2SCFGR_CKPOL bit
|
||||
*/
|
||||
|
||||
/* Write to SPIx I2SCFGR */
|
||||
MODIFY_REG(SPIx->I2SCFGR,
|
||||
I2S_I2SCFGR_CLEAR_MASK,
|
||||
I2S_InitStruct->Mode | I2S_InitStruct->Standard |
|
||||
I2S_InitStruct->DataFormat | I2S_InitStruct->ClockPolarity |
|
||||
SPI_I2SCFGR_I2SMOD);
|
||||
|
||||
/*---------------------------- SPIx I2SPR Configuration ----------------------
|
||||
* Configure SPIx I2SPR with parameters:
|
||||
* - MCLKOutput: SPI_I2SPR_MCKOE bit
|
||||
* - AudioFreq: SPI_I2SPR_I2SDIV[7:0] and SPI_I2SPR_ODD bits
|
||||
*/
|
||||
|
||||
/* If the requested audio frequency is not the default, compute the prescaler (i2sodd, i2sdiv)
|
||||
* else, default values are used: i2sodd = 0U, i2sdiv = 2U.
|
||||
*/
|
||||
if (I2S_InitStruct->AudioFreq != LL_I2S_AUDIOFREQ_DEFAULT)
|
||||
{
|
||||
/* Check the frame length (For the Prescaler computing)
|
||||
* Default value: LL_I2S_DATAFORMAT_16B (packetlength = 1U).
|
||||
*/
|
||||
if (I2S_InitStruct->DataFormat != LL_I2S_DATAFORMAT_16B)
|
||||
{
|
||||
/* Packet length is 32 bits */
|
||||
packetlength = 2U;
|
||||
}
|
||||
|
||||
#if defined (SPI_I2S_FULLDUPLEX_SUPPORT)
|
||||
/* If an external I2S clock has to be used, the specific define should be set
|
||||
in the project configuration or in the stm32f3xx_ll_rcc.h file */
|
||||
/* Get the I2S source clock value */
|
||||
sourceclock = LL_RCC_GetI2SClockFreq(LL_RCC_I2S_CLKSOURCE);
|
||||
#else /* Case for STM32F373xC and STM32F378xx series */
|
||||
/* I2S Clock source is System clock: Get System Clock frequency */
|
||||
LL_RCC_GetSystemClocksFreq(&rcc_clocks);
|
||||
if (SPIx == SPI1)
|
||||
{
|
||||
sourceclock = rcc_clocks.PCLK2_Frequency;
|
||||
}
|
||||
else /* SPI2 or SPI3 */
|
||||
{
|
||||
sourceclock = rcc_clocks.PCLK1_Frequency;
|
||||
}
|
||||
|
||||
#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */
|
||||
|
||||
/* Compute the Real divider depending on the MCLK output state with a floating point */
|
||||
if (I2S_InitStruct->MCLKOutput == LL_I2S_MCLK_OUTPUT_ENABLE)
|
||||
{
|
||||
/* MCLK output is enabled */
|
||||
tmp = (((((sourceclock / 256U) * 10U) / I2S_InitStruct->AudioFreq)) + 5U);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* MCLK output is disabled */
|
||||
tmp = (((((sourceclock / (32U * packetlength)) * 10U) / I2S_InitStruct->AudioFreq)) + 5U);
|
||||
}
|
||||
|
||||
/* Remove the floating point */
|
||||
tmp = tmp / 10U;
|
||||
|
||||
/* Check the parity of the divider */
|
||||
i2sodd = (tmp & (uint16_t)0x0001U);
|
||||
|
||||
/* Compute the i2sdiv prescaler */
|
||||
i2sdiv = ((tmp - i2sodd) / 2U);
|
||||
|
||||
/* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */
|
||||
i2sodd = (i2sodd << 8U);
|
||||
}
|
||||
|
||||
/* Test if the divider is 1 or 0 or greater than 0xFF */
|
||||
if ((i2sdiv < 2U) || (i2sdiv > 0xFFU))
|
||||
{
|
||||
/* Set the default values */
|
||||
i2sdiv = 2U;
|
||||
i2sodd = 0U;
|
||||
}
|
||||
|
||||
/* Write to SPIx I2SPR register the computed value */
|
||||
WRITE_REG(SPIx->I2SPR, i2sdiv | i2sodd | I2S_InitStruct->MCLKOutput);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_I2S_InitTypeDef field to default value.
|
||||
* @param I2S_InitStruct pointer to a @ref LL_I2S_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_I2S_StructInit(LL_I2S_InitTypeDef *I2S_InitStruct)
|
||||
{
|
||||
/*--------------- Reset I2S init structure parameters values -----------------*/
|
||||
I2S_InitStruct->Mode = LL_I2S_MODE_SLAVE_TX;
|
||||
I2S_InitStruct->Standard = LL_I2S_STANDARD_PHILIPS;
|
||||
I2S_InitStruct->DataFormat = LL_I2S_DATAFORMAT_16B;
|
||||
I2S_InitStruct->MCLKOutput = LL_I2S_MCLK_OUTPUT_DISABLE;
|
||||
I2S_InitStruct->AudioFreq = LL_I2S_AUDIOFREQ_DEFAULT;
|
||||
I2S_InitStruct->ClockPolarity = LL_I2S_POLARITY_LOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set linear and parity prescaler.
|
||||
* @note To calculate value of PrescalerLinear(I2SDIV[7:0] bits) and PrescalerParity(ODD bit)\n
|
||||
* Check Audio frequency table and formulas inside Reference Manual (SPI/I2S).
|
||||
* @param SPIx SPI Instance
|
||||
* @param PrescalerLinear value Min_Data=0x02 and Max_Data=0xFF.
|
||||
* @param PrescalerParity This parameter can be one of the following values:
|
||||
* @arg @ref LL_I2S_PRESCALER_PARITY_EVEN
|
||||
* @arg @ref LL_I2S_PRESCALER_PARITY_ODD
|
||||
* @retval None
|
||||
*/
|
||||
void LL_I2S_ConfigPrescaler(SPI_TypeDef *SPIx, uint32_t PrescalerLinear, uint32_t PrescalerParity)
|
||||
{
|
||||
/* Check the I2S parameters */
|
||||
assert_param(IS_I2S_ALL_INSTANCE(SPIx));
|
||||
assert_param(IS_LL_I2S_PRESCALER_LINEAR(PrescalerLinear));
|
||||
assert_param(IS_LL_I2S_PRESCALER_PARITY(PrescalerParity));
|
||||
|
||||
/* Write to SPIx I2SPR */
|
||||
MODIFY_REG(SPIx->I2SPR, SPI_I2SPR_I2SDIV | SPI_I2SPR_ODD, PrescalerLinear | (PrescalerParity << 8U));
|
||||
}
|
||||
|
||||
#if defined (SPI_I2S_FULLDUPLEX_SUPPORT)
|
||||
/**
|
||||
* @brief Configures the full duplex mode for the I2Sx peripheral using its extension
|
||||
* I2Sxext according to the specified parameters in the I2S_InitStruct.
|
||||
* @note The structure pointed by I2S_InitStruct parameter should be the same
|
||||
* used for the master I2S peripheral. In this case, if the master is
|
||||
* configured as transmitter, the slave will be receiver and vice versa.
|
||||
* Or you can force a different mode by modifying the field I2S_Mode to the
|
||||
* value I2S_SlaveRx or I2S_SlaveTx independently of the master configuration.
|
||||
* @param I2Sxext SPI Instance
|
||||
* @param I2S_InitStruct pointer to a @ref LL_I2S_InitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: I2Sxext registers are Initialized
|
||||
* - ERROR: I2Sxext registers are not Initialized
|
||||
*/
|
||||
ErrorStatus LL_I2S_InitFullDuplex(SPI_TypeDef *I2Sxext, LL_I2S_InitTypeDef *I2S_InitStruct)
|
||||
{
|
||||
uint32_t mode = 0U;
|
||||
ErrorStatus status = ERROR;
|
||||
|
||||
/* Check the I2S parameters */
|
||||
assert_param(IS_I2S_EXT_ALL_INSTANCE(I2Sxext));
|
||||
assert_param(IS_LL_I2S_MODE(I2S_InitStruct->Mode));
|
||||
assert_param(IS_LL_I2S_STANDARD(I2S_InitStruct->Standard));
|
||||
assert_param(IS_LL_I2S_DATAFORMAT(I2S_InitStruct->DataFormat));
|
||||
assert_param(IS_LL_I2S_CPOL(I2S_InitStruct->ClockPolarity));
|
||||
|
||||
if (LL_I2S_IsEnabled(I2Sxext) == 0x00000000U)
|
||||
{
|
||||
/*---------------------------- SPIx I2SCFGR Configuration --------------------
|
||||
* Configure SPIx I2SCFGR with parameters:
|
||||
* - Mode: SPI_I2SCFGR_I2SCFG[1:0] bit
|
||||
* - Standard: SPI_I2SCFGR_I2SSTD[1:0] and SPI_I2SCFGR_PCMSYNC bits
|
||||
* - DataFormat: SPI_I2SCFGR_CHLEN and SPI_I2SCFGR_DATLEN bits
|
||||
* - ClockPolarity: SPI_I2SCFGR_CKPOL bit
|
||||
*/
|
||||
|
||||
/* Reset I2SPR registers */
|
||||
WRITE_REG(I2Sxext->I2SPR, I2S_I2SPR_CLEAR_MASK);
|
||||
|
||||
/* Get the mode to be configured for the extended I2S */
|
||||
if ((I2S_InitStruct->Mode == LL_I2S_MODE_MASTER_TX) || (I2S_InitStruct->Mode == LL_I2S_MODE_SLAVE_TX))
|
||||
{
|
||||
mode = LL_I2S_MODE_SLAVE_RX;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((I2S_InitStruct->Mode == LL_I2S_MODE_MASTER_RX) || (I2S_InitStruct->Mode == LL_I2S_MODE_SLAVE_RX))
|
||||
{
|
||||
mode = LL_I2S_MODE_SLAVE_TX;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write to SPIx I2SCFGR */
|
||||
MODIFY_REG(I2Sxext->I2SCFGR,
|
||||
I2S_I2SCFGR_CLEAR_MASK,
|
||||
I2S_InitStruct->Standard |
|
||||
I2S_InitStruct->DataFormat | I2S_InitStruct->ClockPolarity |
|
||||
SPI_I2SCFGR_I2SMOD | mode);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* SPI_I2S_SUPPORT */
|
||||
|
||||
#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) || defined (SPI4) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - FAT file system module configuration file R0.12 (C)ChaN, 2016
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _FFCONF 88100 /* Revision ID */
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _FS_READONLY 0
|
||||
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
|
||||
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
|
||||
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
|
||||
/ and optional writing functions as well. */
|
||||
|
||||
|
||||
#define _FS_MINIMIZE 0
|
||||
/* This option defines minimization level to remove some basic API functions.
|
||||
/
|
||||
/ 0: All basic functions are enabled.
|
||||
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
|
||||
/ are removed.
|
||||
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
|
||||
/ 3: f_lseek() function is removed in addition to 2. */
|
||||
|
||||
|
||||
#define _USE_STRFUNC 2 /* 0:Disable or 1-2:Enable */
|
||||
/* This option switches string functions, f_gets(), f_putc(), f_puts() and
|
||||
/ f_printf().
|
||||
/
|
||||
/ 0: Disable string functions.
|
||||
/ 1: Enable without LF-CRLF conversion.
|
||||
/ 2: Enable with LF-CRLF conversion. */
|
||||
|
||||
|
||||
#define _USE_FIND 0
|
||||
/* This option switches filtered directory read functions, f_findfirst() and
|
||||
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
|
||||
|
||||
|
||||
#define _USE_MKFS 0
|
||||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define _USE_FASTSEEK 0
|
||||
/* This option switches fast seek function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define _USE_EXPAND 0
|
||||
/* This option switches f_expand function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define _USE_CHMOD 0
|
||||
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
|
||||
/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
|
||||
|
||||
|
||||
#define _USE_LABEL 0
|
||||
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
||||
/ (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define _USE_FORWARD 0
|
||||
/* This option switches f_forward() function. (0:Disable or 1:Enable)
|
||||
/ To enable it, also _FS_TINY need to be 1. */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Locale and Namespace Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _CODE_PAGE 437
|
||||
/* This option specifies the OEM code page to be used on the target system.
|
||||
/ Incorrect setting of the code page can cause a file open failure.
|
||||
/
|
||||
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
|
||||
/ 437 - U.S.
|
||||
/ 720 - Arabic
|
||||
/ 737 - Greek
|
||||
/ 771 - KBL
|
||||
/ 775 - Baltic
|
||||
/ 850 - Latin 1
|
||||
/ 852 - Latin 2
|
||||
/ 855 - Cyrillic
|
||||
/ 857 - Turkish
|
||||
/ 860 - Portuguese
|
||||
/ 861 - Icelandic
|
||||
/ 862 - Hebrew
|
||||
/ 863 - Canadian French
|
||||
/ 864 - Arabic
|
||||
/ 865 - Nordic
|
||||
/ 866 - Russian
|
||||
/ 869 - Greek 2
|
||||
/ 932 - Japanese (DBCS)
|
||||
/ 936 - Simplified Chinese (DBCS)
|
||||
/ 949 - Korean (DBCS)
|
||||
/ 950 - Traditional Chinese (DBCS)
|
||||
*/
|
||||
|
||||
|
||||
#define _USE_LFN 1 /* 0 to 3 */
|
||||
#define _MAX_LFN 255
|
||||
/* The _USE_LFN switches the support of long file name (LFN).
|
||||
/
|
||||
/ 0: Disable support of LFN. _MAX_LFN has no effect.
|
||||
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
|
||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
||||
/
|
||||
/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
|
||||
/ to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and
|
||||
/ additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255.
|
||||
/ It should be set 255 to support full featured LFN operations.
|
||||
/ When use stack for the working buffer, take care on stack overflow. When use heap
|
||||
/ memory for the working buffer, memory management functions, ff_memalloc() and
|
||||
/ ff_memfree(), must be added to the project. */
|
||||
|
||||
|
||||
#define _LFN_UNICODE 0
|
||||
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode)
|
||||
/ To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1.
|
||||
/ This option also affects behavior of string I/O functions. */
|
||||
|
||||
|
||||
#define _STRF_ENCODE 3
|
||||
/* When _LFN_UNICODE == 1, this option selects the character encoding on the file to
|
||||
/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
|
||||
/
|
||||
/ 0: ANSI/OEM
|
||||
/ 1: UTF-16LE
|
||||
/ 2: UTF-16BE
|
||||
/ 3: UTF-8
|
||||
/
|
||||
/ This option has no effect when _LFN_UNICODE == 0. */
|
||||
|
||||
|
||||
#define _FS_RPATH 0
|
||||
/* This option configures support of relative path.
|
||||
/
|
||||
/ 0: Disable relative path and remove related functions.
|
||||
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
|
||||
/ 2: f_getcwd() function is available in addition to 1.
|
||||
*/
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Drive/Volume Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _VOLUMES 1
|
||||
/* Number of volumes (logical drives) to be used. */
|
||||
|
||||
|
||||
#define _STR_VOLUME_ID 0
|
||||
#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
|
||||
/* _STR_VOLUME_ID switches string support of volume ID.
|
||||
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
|
||||
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
|
||||
/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
|
||||
/ the drive ID strings are: A-Z and 0-9. */
|
||||
|
||||
|
||||
#define _MULTI_PARTITION 0
|
||||
/* This option switches support of multi-partition on a physical drive.
|
||||
/ By default (0), each logical drive number is bound to the same physical drive
|
||||
/ number and only an FAT volume found on the physical drive will be mounted.
|
||||
/ When multi-partition is enabled (1), each logical drive number can be bound to
|
||||
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
|
||||
/ funciton will be available. */
|
||||
|
||||
|
||||
#define _MIN_SS 512
|
||||
#define _MAX_SS 512
|
||||
/* These options configure the range of sector size to be supported. (512, 1024,
|
||||
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
|
||||
/ harddisk. But a larger value may be required for on-board flash memory and some
|
||||
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
|
||||
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
|
||||
/ disk_ioctl() function. */
|
||||
|
||||
|
||||
#define _USE_TRIM 0
|
||||
/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable)
|
||||
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
|
||||
/ disk_ioctl() function. */
|
||||
|
||||
|
||||
#define _FS_NOFSINFO 0
|
||||
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
|
||||
/ option, and f_getfree() function at first time after volume mount will force
|
||||
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
|
||||
/
|
||||
/ bit0=0: Use free cluster count in the FSINFO if available.
|
||||
/ bit0=1: Do not trust free cluster count in the FSINFO.
|
||||
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
|
||||
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ System Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _FS_TINY 0
|
||||
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
|
||||
/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS bytes.
|
||||
/ Instead of private sector buffer eliminated from the file object, common sector
|
||||
/ buffer in the file system object (FATFS) is used for the file data transfer. */
|
||||
|
||||
|
||||
#define _FS_EXFAT 0
|
||||
/* This option switches support of exFAT file system in addition to the traditional
|
||||
/ FAT file system. (0:Disable or 1:Enable) To enable exFAT, also LFN must be enabled.
|
||||
/ Note that enabling exFAT discards C89 compatibility. */
|
||||
|
||||
|
||||
#define _FS_NORTC 1
|
||||
#define _NORTC_MON 3
|
||||
#define _NORTC_MDAY 1
|
||||
#define _NORTC_YEAR 2016
|
||||
/* The option _FS_NORTC switches timestamp functiton. If the system does not have
|
||||
/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
|
||||
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
|
||||
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
|
||||
/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
|
||||
/ added to the project to get current time form real-time clock. _NORTC_MON,
|
||||
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
|
||||
/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
|
||||
|
||||
|
||||
#define _FS_LOCK 0
|
||||
/* The option _FS_LOCK switches file lock function to control duplicated file open
|
||||
/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
|
||||
/ is 1.
|
||||
/
|
||||
/ 0: Disable file lock function. To avoid volume corruption, application program
|
||||
/ should avoid illegal open, remove and rename to the open objects.
|
||||
/ >0: Enable file lock function. The value defines how many files/sub-directories
|
||||
/ can be opened simultaneously under file lock control. Note that the file
|
||||
/ lock control is independent of re-entrancy. */
|
||||
|
||||
|
||||
#define _FS_REENTRANT 0
|
||||
#define _FS_TIMEOUT 1000
|
||||
#define _SYNC_t HANDLE
|
||||
/* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
|
||||
/ module itself. Note that regardless of this option, file access to different
|
||||
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
|
||||
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
|
||||
/ to the same volume is under control of this function.
|
||||
/
|
||||
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
|
||||
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
|
||||
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
|
||||
/ function, must be added to the project. Samples are available in
|
||||
/ option/syscall.c.
|
||||
/
|
||||
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
|
||||
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
|
||||
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
|
||||
/ included somewhere in the scope of ff.c. */
|
||||
|
||||
|
||||
/*--- End of configuration options ---*/
|
|
@ -0,0 +1,680 @@
|
|||
/*------------------------------------------------------------------------/
|
||||
/ MMCv3/SDv1/SDv2 (in SPI mode) control module
|
||||
/-------------------------------------------------------------------------/
|
||||
/
|
||||
/ Copyright (C) 2013, ChaN, all right reserved.
|
||||
/
|
||||
/ * This software is a free software and there is NO WARRANTY.
|
||||
/ * No restriction on use. You can use, modify and redistribute it for
|
||||
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
|
||||
/ * Redistributions of source code must retain the above copyright notice.
|
||||
/
|
||||
/-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* This file was modified from a sample available from the FatFs
|
||||
* web site. It was modified to work with a Olimexino-STM32F3
|
||||
* evaluation board.
|
||||
*
|
||||
*/
|
||||
#include "diskio.h"
|
||||
#include "stm32f3xx.h" /* STM32 registers and drivers */
|
||||
#include "stm32f3xx_ll_bus.h" /* STM32 LL BUS header */
|
||||
#include "stm32f3xx_ll_gpio.h" /* STM32 LL GPIO header */
|
||||
#include "stm32f3xx_ll_spi.h" /* STM32 LL SPI header */
|
||||
#include "boot.h"
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
Macro Definitions
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
/* MMC card type flags (MMC_GET_TYPE) */
|
||||
#define CT_MMC 0x01 /* MMC ver 3 */
|
||||
#define CT_SD1 0x02 /* SD ver 1 */
|
||||
#define CT_SD2 0x04 /* SD ver 2 */
|
||||
#define CT_SDC (CT_SD1|CT_SD2) /* SD */
|
||||
#define CT_BLOCK 0x08 /* Block addressing */
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
Module Private Functions
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* Definitions for MMC/SDC command */
|
||||
#define CMD0 (0) /* GO_IDLE_STATE */
|
||||
#define CMD1 (1) /* SEND_OP_COND */
|
||||
#define ACMD41 (41|0x80) /* SEND_OP_COND (SDC) */
|
||||
#define CMD8 (8) /* SEND_IF_COND */
|
||||
#define CMD9 (9) /* SEND_CSD */
|
||||
#define CMD10 (10) /* SEND_CID */
|
||||
#define CMD12 (12) /* STOP_TRANSMISSION */
|
||||
#define ACMD13 (13|0x80) /* SD_STATUS (SDC) */
|
||||
#define CMD16 (16) /* SET_BLOCKLEN */
|
||||
#define CMD17 (17) /* READ_SINGLE_BLOCK */
|
||||
#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
|
||||
#define CMD23 (23) /* SET_BLOCK_COUNT */
|
||||
#define ACMD23 (23|0x80) /* SET_WR_BLK_ERASE_COUNT (SDC) */
|
||||
#define CMD24 (24) /* WRITE_BLOCK */
|
||||
#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
|
||||
#define CMD41 (41) /* SEND_OP_COND (ACMD) */
|
||||
#define CMD55 (55) /* APP_CMD */
|
||||
#define CMD58 (58) /* READ_OCR */
|
||||
|
||||
|
||||
/* Control signals (Platform dependent) */
|
||||
#define CS_LOW() LL_GPIO_ResetOutputPin(GPIOD, LL_GPIO_PIN_2) /* MMC CS = L */
|
||||
#define CS_HIGH() LL_GPIO_SetOutputPin(GPIOD, LL_GPIO_PIN_2) /* MMC CS = H */
|
||||
|
||||
|
||||
#define FCLK_SLOW() /* Set slow clock (100k-400k) */
|
||||
#define FCLK_FAST() set_max_speed() /* Set fast clock (depends on the CSD) */
|
||||
|
||||
static volatile
|
||||
DSTATUS Stat = STA_NOINIT; /* Disk status */
|
||||
|
||||
static
|
||||
UINT CardType;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Transmit/Receive data to/from MMC via SPI (Platform dependent) */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
static
|
||||
BYTE xchg_spi (BYTE dat)
|
||||
{
|
||||
BYTE result = 0;
|
||||
DWORD timeOutTime;
|
||||
BYTE timeoutDetected = 0;
|
||||
|
||||
/* Send byte through the SPI peripheral */
|
||||
LL_SPI_TransmitData8(SPI2, dat);
|
||||
|
||||
/* Set timeout for 50 ms from now */
|
||||
timeOutTime = TimerGet() + 50;
|
||||
|
||||
/* Wait to receive a byte with timeout */
|
||||
while (LL_SPI_IsActiveFlag_RXNE(SPI2) == 0)
|
||||
{
|
||||
/* Service the watchdog */
|
||||
CopService();
|
||||
|
||||
/* Check for timeout */
|
||||
if (TimerGet() > timeOutTime)
|
||||
{
|
||||
/* Set flag to remember that a timeout occurred and nothing was received */
|
||||
timeoutDetected = 1;
|
||||
/* Stop waiting */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the value of the received byte */
|
||||
if (timeoutDetected == 0)
|
||||
{
|
||||
result = LL_SPI_ReceiveData8(SPI2);
|
||||
}
|
||||
|
||||
/* Give the result back to the caller */
|
||||
return result;
|
||||
}
|
||||
|
||||
static
|
||||
void rcvr_spi_m (BYTE *dst)
|
||||
{
|
||||
*dst = xchg_spi(0xFF);
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Power Control (Platform dependent) */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* When the target system does not support socket power control, there */
|
||||
/* is nothing to do in these functions. */
|
||||
static
|
||||
void power_on (void)
|
||||
{
|
||||
LL_SPI_InitTypeDef SPI_InitStruct = { 0 };
|
||||
LL_GPIO_InitTypeDef GPIO_InitStruct = { 0 };
|
||||
BYTE n;
|
||||
|
||||
/*
|
||||
* This doesn't really turn the power on, but initializes the
|
||||
* SSI port and pins needed to talk to the card.
|
||||
*/
|
||||
/* Enable SPI and GPIO peripheral clocks. */
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOD);
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
|
||||
/* Configure I/O for Chip select (PD2) */
|
||||
GPIO_InitStruct.Pin = LL_GPIO_PIN_2;
|
||||
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
|
||||
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
||||
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
|
||||
LL_GPIO_Init(GPIOD, &GPIO_InitStruct);
|
||||
/* De-select the Card: Chip Select high */
|
||||
LL_GPIO_SetOutputPin(GPIOD, LL_GPIO_PIN_2);
|
||||
|
||||
/* Configure SPI pins: SCK (PB13), MOSI (PB15) and MISO (PB14) */
|
||||
GPIO_InitStruct.Pin = LL_GPIO_PIN_13 | LL_GPIO_PIN_14 | LL_GPIO_PIN_15;
|
||||
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
|
||||
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
||||
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
|
||||
GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
|
||||
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* SPI2 parameter configuration */
|
||||
SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
|
||||
SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
|
||||
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
|
||||
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
|
||||
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
|
||||
SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
|
||||
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV128; // 36000kHz/128=281kHz < 400kHz
|
||||
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
|
||||
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
|
||||
SPI_InitStruct.CRCPoly = 7;
|
||||
LL_SPI_Init(SPI2, &SPI_InitStruct);
|
||||
LL_SPI_SetStandard(SPI2, LL_SPI_PROTOCOL_MOTOROLA);
|
||||
LL_SPI_DisableNSSPulseMgt(SPI2);
|
||||
LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);
|
||||
LL_SPI_Enable(SPI2);
|
||||
|
||||
/* Apply more than 74 pulses to SCLK, with DI and CS high, for the card to be able to
|
||||
* accept a native command at SCLK < 400 kHz.
|
||||
*/
|
||||
for (n = 10; n; n--)
|
||||
{
|
||||
xchg_spi(0xFF); /* Send 80 dummy clocks */
|
||||
}
|
||||
}
|
||||
|
||||
// set the SSI speed to the max setting
|
||||
static
|
||||
void set_max_speed(void)
|
||||
{
|
||||
LL_SPI_InitTypeDef SPI_InitStruct;
|
||||
|
||||
/* Disable the SPI system */
|
||||
LL_SPI_Disable(SPI2);
|
||||
|
||||
/* MMC/SDC can work at the clock frequency up to 20/25MHz so pick a speed close to
|
||||
* this but not higher
|
||||
*/
|
||||
SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
|
||||
SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
|
||||
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
|
||||
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
|
||||
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
|
||||
SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
|
||||
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2; // 36MHz/2=18MHz < 20MHz
|
||||
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
|
||||
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
|
||||
SPI_InitStruct.CRCPoly = 7;
|
||||
LL_SPI_Init(SPI2, &SPI_InitStruct);
|
||||
LL_SPI_SetStandard(SPI2, LL_SPI_PROTOCOL_MOTOROLA);
|
||||
LL_SPI_DisableNSSPulseMgt(SPI2);
|
||||
LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);
|
||||
LL_SPI_Enable(SPI2);
|
||||
}
|
||||
|
||||
static
|
||||
void power_off (void)
|
||||
{
|
||||
Stat |= STA_NOINIT; /* Force uninitialized */
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Wait for card ready */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
static
|
||||
int wait_ready (void)
|
||||
{
|
||||
BYTE d;
|
||||
DWORD timeOutTime;
|
||||
|
||||
/* set timeout for 500 ms from now */
|
||||
timeOutTime = TimerGet() + 500;
|
||||
|
||||
do {
|
||||
d = xchg_spi(0xFF);
|
||||
/* Service the watchdog */
|
||||
CopService();
|
||||
} while ((d != 0xFF) && (TimerGet() < timeOutTime));
|
||||
|
||||
return (d == 0xFF) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Deselect the card and release SPI bus */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
static
|
||||
void deselect_card (void)
|
||||
{
|
||||
CS_HIGH();
|
||||
xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Select the card and wait ready */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
static
|
||||
int select_card (void) /* 1:Successful, 0:Timeout */
|
||||
{
|
||||
CS_LOW();
|
||||
xchg_spi(0xFF); /* Dummy clock (force DO enabled) */
|
||||
|
||||
if (wait_ready()) return 1; /* OK */
|
||||
deselect_card();
|
||||
return 0; /* Timeout */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Receive a data packet from MMC */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
static
|
||||
int rcvr_datablock ( /* 1:OK, 0:Failed */
|
||||
BYTE *buff, /* Data buffer to store received data */
|
||||
UINT btr /* Byte count (must be multiple of 4) */
|
||||
)
|
||||
{
|
||||
BYTE token;
|
||||
DWORD timeOutTime;
|
||||
|
||||
/* set timeout for 100 ms from now */
|
||||
timeOutTime = TimerGet() + 100;
|
||||
|
||||
do { /* Wait for data packet in timeout of 100ms */
|
||||
token = xchg_spi(0xFF);
|
||||
/* Service the watchdog */
|
||||
CopService();
|
||||
|
||||
} while ((token == 0xFF) && (TimerGet() < timeOutTime));
|
||||
|
||||
if(token != 0xFE) return 0; /* If not valid data token, retutn with error */
|
||||
|
||||
do { /* Receive the data block into buffer */
|
||||
rcvr_spi_m(buff++);
|
||||
rcvr_spi_m(buff++);
|
||||
/* Service the watchdog */
|
||||
CopService();
|
||||
} while (btr -= 2);
|
||||
xchg_spi(0xFF); /* Discard CRC */
|
||||
xchg_spi(0xFF);
|
||||
|
||||
return 1; /* Return with success */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Send a data packet to MMC */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
static
|
||||
int xmit_datablock ( /* 1:OK, 0:Failed */
|
||||
const BYTE *buff, /* 512 byte data block to be transmitted */
|
||||
BYTE token /* Data token */
|
||||
)
|
||||
{
|
||||
BYTE resp;
|
||||
UINT wc;
|
||||
|
||||
|
||||
if (!wait_ready()) return 0;
|
||||
|
||||
xchg_spi(token); /* Xmit a token */
|
||||
if (token != 0xFD) { /* Not StopTran token */
|
||||
wc = 512;
|
||||
do { /* Xmit the 512 byte data block to MMC */
|
||||
xchg_spi(*buff++);
|
||||
xchg_spi(*buff++);
|
||||
} while (wc -= 2);
|
||||
xchg_spi(0xFF); /* CRC (Dummy) */
|
||||
xchg_spi(0xFF);
|
||||
resp = xchg_spi(0xFF); /* Receive a data response */
|
||||
if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Send a command packet to MMC */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
static
|
||||
BYTE send_cmd (
|
||||
BYTE cmd, /* Command byte */
|
||||
DWORD arg /* Argument */
|
||||
)
|
||||
{
|
||||
BYTE n/*, res*/;
|
||||
static volatile BYTE res = 0;
|
||||
|
||||
|
||||
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
|
||||
cmd &= 0x7F;
|
||||
res = send_cmd(CMD55, 0);
|
||||
if (res > 1) return res;
|
||||
}
|
||||
|
||||
/* Select the card and wait for ready */
|
||||
deselect_card();
|
||||
if (!select_card()) return 0xFF;
|
||||
|
||||
/* Send command packet */
|
||||
xchg_spi(0x40 | cmd); /* Start + Command index */
|
||||
xchg_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
|
||||
xchg_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
|
||||
xchg_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
|
||||
xchg_spi((BYTE)arg); /* Argument[7..0] */
|
||||
n = 0x01; /* Dummy CRC + Stop */
|
||||
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) + Stop */
|
||||
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) + Stop */
|
||||
xchg_spi(n);
|
||||
|
||||
/* Receive command response */
|
||||
if (cmd == CMD12) xchg_spi(0xFF); /* Skip a stuff byte on stop to read */
|
||||
n = 10; /* Wait for a valid response in timeout of 10 attempts */
|
||||
do {
|
||||
res = xchg_spi(0xFF);
|
||||
/* Service the watchdog */
|
||||
CopService();
|
||||
} while ((res & 0x80) && --n);
|
||||
|
||||
return res; /* Return with the response value */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
Public Functions
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Initialize Disk Drive */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_initialize (
|
||||
BYTE pdrv /* Physical drive nmuber (0) */
|
||||
)
|
||||
{
|
||||
BYTE n, cmd, ty, ocr[4];
|
||||
DWORD timeOutTime;
|
||||
|
||||
|
||||
if (pdrv) return STA_NOINIT; /* Supports only single drive */
|
||||
if (Stat & STA_NODISK) return Stat; /* No card in the socket */
|
||||
|
||||
power_on(); /* Force socket power on */
|
||||
|
||||
CS_LOW(); /* CS = L */
|
||||
|
||||
ty = 0;
|
||||
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
|
||||
timeOutTime = TimerGet() + 1000; /* Initialization timeout of 1000 msec */
|
||||
|
||||
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */
|
||||
for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); /* Get trailing return value of R7 resp */
|
||||
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
|
||||
while ((TimerGet() < timeOutTime) && send_cmd(ACMD41, 0x40000000)); /* Wait for leaving idle state (ACMD41 with HCS bit) */
|
||||
if ((TimerGet() < timeOutTime) && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
|
||||
for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);
|
||||
ty = (ocr[0] & 0x40) ? CT_SD2|CT_BLOCK : CT_SD2; /* SDv2 */
|
||||
}
|
||||
}
|
||||
} else { /* SDv1 or MMCv3 */
|
||||
if (send_cmd(ACMD41, 0) <= 1) {
|
||||
ty = CT_SD1; cmd = ACMD41; /* SDv1 */
|
||||
} else {
|
||||
ty = CT_MMC; cmd = CMD1; /* MMCv3 */
|
||||
}
|
||||
while ((TimerGet() < timeOutTime) && send_cmd(cmd, 0)) { /* Wait for leaving idle state */
|
||||
/* Service the watchdog */
|
||||
CopService();
|
||||
}
|
||||
if (!(TimerGet() < timeOutTime) || send_cmd(CMD16, 512) != 0) /* Set read/write block length to 512 */
|
||||
ty = 0;
|
||||
}
|
||||
}
|
||||
CardType = ty;
|
||||
deselect_card();
|
||||
|
||||
if (ty) { /* Initialization succeded */
|
||||
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
|
||||
FCLK_FAST();
|
||||
} else { /* Initialization failed */
|
||||
power_off();
|
||||
}
|
||||
|
||||
return Stat;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Get Disk Status */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_status (
|
||||
BYTE pdrv /* Physical drive nmuber (0) */
|
||||
)
|
||||
{
|
||||
if (pdrv) return STA_NOINIT; /* Supports only single drive */
|
||||
return Stat;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Read Sector(s) */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DRESULT disk_read (
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
BYTE *buff, /* Data buffer to store read data */
|
||||
DWORD sector, /* Sector address in LBA */
|
||||
UINT count /* Number of sectors to read */
|
||||
)
|
||||
{
|
||||
if (pdrv || !count) return RES_PARERR;
|
||||
if (Stat & STA_NOINIT) return RES_NOTRDY;
|
||||
|
||||
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
|
||||
|
||||
if (count == 1) { /* Single block read */
|
||||
if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
|
||||
&& rcvr_datablock(buff, 512))
|
||||
count = 0;
|
||||
}
|
||||
else { /* Multiple block read */
|
||||
if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
|
||||
do {
|
||||
if (!rcvr_datablock(buff, 512)) break;
|
||||
buff += 512;
|
||||
/* Service the watchdog */
|
||||
CopService();
|
||||
} while (--count);
|
||||
send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
|
||||
}
|
||||
}
|
||||
deselect_card();
|
||||
|
||||
return count ? RES_ERROR : RES_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Write Sector(s) */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DRESULT disk_write (
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
const BYTE *buff, /* Data to be written */
|
||||
DWORD sector, /* Sector address in LBA */
|
||||
UINT count /* Number of sectors to write */
|
||||
)
|
||||
{
|
||||
if (pdrv || !count) return RES_PARERR;
|
||||
if (Stat & STA_NOINIT) return RES_NOTRDY;
|
||||
if (Stat & STA_PROTECT) return RES_WRPRT;
|
||||
|
||||
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
|
||||
|
||||
if (count == 1) { /* Single block write */
|
||||
if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
|
||||
&& xmit_datablock(buff, 0xFE))
|
||||
count = 0;
|
||||
}
|
||||
else { /* Multiple block write */
|
||||
if (CardType & CT_SDC) send_cmd(ACMD23, count);
|
||||
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
|
||||
do {
|
||||
if (!xmit_datablock(buff, 0xFC)) break;
|
||||
buff += 512;
|
||||
/* Service the watchdog */
|
||||
CopService();
|
||||
} while (--count);
|
||||
if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
|
||||
count = 1;
|
||||
}
|
||||
}
|
||||
deselect_card();
|
||||
|
||||
return count ? RES_ERROR : RES_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Miscellaneous Functions */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DRESULT disk_ioctl (
|
||||
BYTE pdrv, /* Physical drive nmuber (0) */
|
||||
BYTE cmd, /* Control code */
|
||||
void *buff /* Buffer to send/receive data block */
|
||||
)
|
||||
{
|
||||
DRESULT res;
|
||||
BYTE n, csd[16], *ptr = buff;
|
||||
DWORD csz;
|
||||
|
||||
|
||||
if (pdrv) return RES_PARERR;
|
||||
if (Stat & STA_NOINIT) return RES_NOTRDY;
|
||||
|
||||
res = RES_ERROR;
|
||||
switch (cmd) {
|
||||
case CTRL_SYNC : /* Flush write-back cache, Wait for end of internal process */
|
||||
if (select_card()) res = RES_OK;
|
||||
break;
|
||||
|
||||
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (WORD) */
|
||||
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
|
||||
if ((csd[0] >> 6) == 1) { /* SDv2? */
|
||||
csz = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1;
|
||||
*(DWORD*)buff = csz << 10;
|
||||
} else { /* SDv1 or MMCv3 */
|
||||
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
|
||||
csz = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
|
||||
*(DWORD*)buff = csz << (n - 9);
|
||||
}
|
||||
res = RES_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_BLOCK_SIZE : /* Get erase block size in unit of sectors (DWORD) */
|
||||
if (CardType & CT_SD2) { /* SDv2? */
|
||||
if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */
|
||||
xchg_spi(0xFF);
|
||||
if (rcvr_datablock(csd, 16)) { /* Read partial block */
|
||||
for (n = 64 - 16; n; n--) xchg_spi(0xFF); /* Purge trailing data */
|
||||
*(DWORD*)buff = 16UL << (csd[10] >> 4);
|
||||
res = RES_OK;
|
||||
}
|
||||
}
|
||||
} else { /* SDv1 or MMCv3 */
|
||||
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */
|
||||
if (CardType & CT_SD1) { /* SDv1 */
|
||||
*(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
|
||||
} else { /* MMCv3 */
|
||||
*(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
|
||||
}
|
||||
res = RES_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MMC_GET_TYPE : /* Get card type flags (1 byte) */
|
||||
*ptr = CardType;
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
|
||||
if ((send_cmd(CMD9, 0) == 0) /* READ_CSD */
|
||||
&& rcvr_datablock(buff, 16))
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
|
||||
if ((send_cmd(CMD10, 0) == 0) /* READ_CID */
|
||||
&& rcvr_datablock(buff, 16))
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
|
||||
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
|
||||
for (n = 0; n < 4; n++) {
|
||||
*((BYTE*)buff+n) = xchg_spi(0xFF);
|
||||
/* Service the watchdog */
|
||||
CopService();
|
||||
}
|
||||
res = RES_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case MMC_GET_SDSTAT : /* Receive SD status as a data block (64 bytes) */
|
||||
if ((CardType & CT_SD2) && send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
|
||||
xchg_spi(0xFF);
|
||||
if (rcvr_datablock(buff, 64))
|
||||
res = RES_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
res = RES_PARERR;
|
||||
}
|
||||
|
||||
deselect_card();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ MEMORY
|
|||
{
|
||||
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 8K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 40K
|
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 32K
|
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 40K
|
||||
}
|
||||
|
||||
/* Sections */
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-804685279247832828" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-666769791631151900" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
|
@ -16,7 +16,7 @@
|
|||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-804685279247832828" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-666769791631151900" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -47,7 +47,7 @@ MEMORY
|
|||
{
|
||||
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 8K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 40K
|
||||
FLASH (rx) : ORIGIN = 0x08008000, LENGTH = 256K - 32K
|
||||
FLASH (rx) : ORIGIN = 0x0800A000, LENGTH = 256K - 40K
|
||||
}
|
||||
|
||||
/* Sections */
|
||||
|
|
Loading…
Reference in New Issue