Keil MDK使用中间件在RAM上创建文件系统

前言

软件版本信息:Keil MDK v5.26

硬件开发板:STM32F429I-Discovery

 

工程创建

下载STM32F4系列的pack包https://www.keil.com/dd2/pack/

新建工程

利用Manage Run-Time Environment配置工程

  • 添加Keil RTX实时操作系统

具体需要添加的

Board SupportLED
CMSISCORE
Keil RTX
CompilerEvent Recorder
File
DeviceStartup
Classic
USART
SPI
SDRAM
RCC
PWR
I2C
GPIO
DMA
Cortex
Common
File SystemCORE

RAM

将stm32f4xx_it.c文件中三个函数注释了,因为这三个函数被Keil RTX实时操作系统占用了

void SysTick_Handler(void)

void PendSV_Handler(void)

void SVC_Handler(void)

管理工程

创建多个Groups用于区分不同部分代码使工程结构更加清晰

添加stm32f429I中的SDRAM实例文件stm32f429i_discovery_sdram.c文件。这里不再讲如何初始化SDRAM直接用别人程序就行

这里需要使用void BSP_SDRAM_Init(void)来初始化开发上的SDRAM

添加线程

选择工程结构的Threads文件夹,右键Add new items into Groups。然后选择CMSIS-RTOS thread模板

向文件中添加以下代码——线程创建、文件系统创建:

注意:保存文件系统的设备(Flash、SD卡、SDRAM等)需要格式化


#include "cmsis_os.h"                                           // CMSIS RTOS header file
#include "rl_fs.h"                      // Keil.MDK-Plus::File System:CORE
#include "Board_LED.h"                  // ::Board Support:LED
#include <stdio.h>
/*----------------------------------------------------------------------------
 *      Thread 1 'Thread_Name': Sample thread
 *---------------------------------------------------------------------------*/
 
void Thread (void const *argument);                             // thread function
osThreadId tid_Thread;                                          // thread id
osThreadDef (Thread, osPriorityNormal, 1, 0);                   // thread object

static char *get_drive (char *src, char *dst, uint32_t dst_sz) {
  uint32_t i, n;

  i = 0;
  n = 0;
  while (!n && src && src[i] && (i < dst_sz)) {
    dst[i] = src[i];

    if (dst[i] == ':') {
      n = i + 1;
    }
    i++;
  }
  if (n == dst_sz) {
    n = 0;
  }
  dst[n] = '\0';

  return (src + n);
}


static void cmd_format (char *par) {
  char  label[12];
  char  drive[4];
  //int   retv;
  char *opt;
  // Set formatting options
  opt = "/W /L RAMDRIVE";  // Do not use /FAT32, ram drive space is too small
  par = get_drive (par, drive, 4);	//多余的代码

  printf ("\nProceed with Format [Y/N]\n");
//格式化设备这行代码非常重要,如果驱动正常。初始化一直失败说没有“文件系统卷宗”。那么就是这里出问题了即没有格式化!!!
    if (fformat (drive, opt) == fsOK) {   // file:///C:/Keil_v5/ARM/PACK/Keil/MDK-Middleware/7.9.0-dev4/Doc/FileSystem/html/group__utility__routines.html#gaea20173a589e298b86791f1cc661731b
      printf ("Format completed.\n");
      if (fvol (drive, label, NULL) == 0) {
        if (label[0] != '\0') {
          printf ("Volume label is \"%s\"\n", label);
        }
      }
    }
    else {
      printf ("Formatting failed.\n");
    }
  /*}
  else {
    printf ("Formatting canceled.\n");
  }*/
}

static void init_filesystem (void) {
  fsStatus stat;

  printf ("Initializing and mounting enabled drives...\n\n");

	
	stat = finit ("R0:");
  if (stat == fsOK) {
    stat = fmount ("R0:");
    if (stat == fsOK) {
      printf ("Drive R0 ready!\n");
    }
    else if (stat == fsNoFileSystem) {
      // Format the drive 
      printf ("Drive R0 not formatted!\n");
      cmd_format ("R0:");
			stat = fmount ("R0:");
			if (stat != fsOK) {
				LED_On(0);
			}
    }
    else {
      printf ("Drive R0 mount failed with error code %d\n", stat);
    }
  }
  else {
    printf ("Drive R0 initialization failed!\n");
  }

  printf ("\nDone!\n");
}

int Init_Thread (void) {

	FILE *f;
  tid_Thread = osThreadCreate (osThread(Thread), NULL);
  if (!tid_Thread) return(-1);
  
	init_filesystem();
//	if(finit("R0:") != fsOK)
//	{
//			LED_On(0);
//	}
//	fstat = fmount("R0:");

	f = fopen("R0:\\Test.log","w");
	if(f == NULL)
	{
			LED_On(1);
	}
	else
	{
			fclose(f);
	}
	
  return(0);
}

void Thread (void const *argument) {

  while (1) {
    ; // Insert thread code here...
    osThreadYield ();                                           // suspend thread
  }
}

注意:文件系统中间件的使用,请参考MDK中Manage Run-Time Environment相应的帮助文档

点击“蓝色”链接文字即可打开帮助文档。文档中有API使用以及相关例程

编写主程序中的代码。主要功能:初始化SDRAM设备

/**
  ******************************************************************************
  * @file    Templates/Src/main.c 
  * @author  MCD Application Team
  * @version V1.2.4
  * @date    06-May-2016
  * @brief   Main program body
  *
  * @note    modified by ARM
  *          The modifications allow to use this file as User Code Template
  *          within the Device Family Pack.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f429i_discovery.h"
#include "stm32f429i_discovery_sdram.h"
#include "Board_LED.h"                  // ::Board Support:LED

#ifdef RTE_Compiler_EventRecorder
#include "EventRecorder.h"
#endif

#ifdef _RTE_
#include "RTE_Components.h"             /* Component selection */
#endif
#ifdef RTE_CMSIS_RTOS                   // when RTE component CMSIS RTOS is used
#include "cmsis_os.h"                   // CMSIS RTOS header file
#endif

#ifdef RTE_CMSIS_RTOS_RTX
extern uint32_t os_time;

uint32_t HAL_GetTick(void) { 
  return os_time; 
}
#endif

/** @addtogroup STM32F4xx_HAL_Examples
  * @{
  */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define BUFFER_SIZE         ((uint32_t)0x0100)
#define WRITE_READ_ADDR     ((uint32_t)0x0800)

/** @addtogroup Templates
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static void Error_Handler(void);

/* Private functions ---------------------------------------------------------*/
/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
/**
  * @brief  Fills buffer with user predefined data.
  * @param  pBuffer: pointer on the buffer to fill
  * @param  uwBufferLenght: size of the buffer to fill
  * @param  uwOffset: first value to fill on the buffer
  * @retval None
  */
static void Fill_Buffer(uint32_t *pBuffer, uint32_t uwBufferLenght, uint32_t uwOffset)
{
  uint32_t tmpIndex = 0;

  /* Put in global buffer different values */
  for (tmpIndex = 0; tmpIndex < uwBufferLenght; tmpIndex++ )
  {
    pBuffer[tmpIndex] = tmpIndex + uwOffset;
  }
} 	

extern int Init_Thread (void);
	
/* Counter index */
uint32_t uwIndex = 0;
/* Read/Write Buffers */
uint32_t aTxBuffer[BUFFER_SIZE];
uint32_t aRxBuffer[BUFFER_SIZE];

/* Status variables */
__IO uint32_t uwWriteReadStatus = 0;

int main(void)
{
uint32_t data_test = 123456;
uint32_t data_test_rec = 0;
#ifdef RTE_CMSIS_RTOS                   // when using CMSIS RTOS
  osKernelInitialize();                 // initialize CMSIS-RTOS
#endif

  /* STM32F4xx HAL library initialization:
       - Configure the Flash prefetch, Flash preread and Buffer caches
       - Systick timer is configured by default as source of time base, but user 
             can eventually implement his proper time base source (a general purpose 
             timer for example or other time source), keeping in mind that Time base 
             duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and 
             handled in milliseconds basis.
       - Low Level Initialization
     */
  HAL_Init();

	
  /* Configure the system clock to 168 MHz */
  SystemClock_Config();

  /* Add your application code here
     */
	LED_Initialize();	 
	BSP_SDRAM_Init();//初始化SDRAM
	
	//KRB
#ifdef RTE_Compiler_EventRecorder
  EventRecorderInitialize(0, 1);
  EventRecorderEnable (EventRecordError, 0x80U, 0x87U);  /* FS Error Events */
  EventRecorderEnable (EventRecordAll  , 0x81U, 0x81U);  /* FAT Events */
#endif
	
	Init_Thread();
	
	BSP_SDRAM_WriteData(SDRAM_DEVICE_ADDR,&data_test,1);
	BSP_SDRAM_ReadData(SDRAM_DEVICE_ADDR,&data_test_rec,1);
	if(data_test == data_test_rec)
	{
		LED_On(0);
	}
	else
	{
		LED_On(1);
	}

	#if 0
			 /* Fill the buffer to write */
  Fill_Buffer(aTxBuffer, BUFFER_SIZE, 0xA244250F);   
  
  /* Write data to the SDRAM memory */
  for (uwIndex = 0; uwIndex < BUFFER_SIZE; uwIndex++)
  {
    *(__IO uint32_t*) (SDRAM_DEVICE_ADDR + WRITE_READ_ADDR + 4*uwIndex) = aTxBuffer[uwIndex];
  }    
  
  /* Read back data from the SDRAM memory */
  for (uwIndex = 0; uwIndex < BUFFER_SIZE; uwIndex++)
  {
    aRxBuffer[uwIndex] = *(__IO uint32_t*) (SDRAM_DEVICE_ADDR + WRITE_READ_ADDR + 4*uwIndex);
   } 
	 /* Read back data from the SDRAM memory */
  for (uwIndex = 0; uwIndex < BUFFER_SIZE; uwIndex++)
  {
    aRxBuffer[uwIndex] = *(__IO uint32_t*) (SDRAM_DEVICE_ADDR + WRITE_READ_ADDR + 4*uwIndex);
   } 

  /*##-3- Checking data integrity ############################################*/    

  for (uwIndex = 0; (uwIndex < BUFFER_SIZE) && (uwWriteReadStatus == 0); uwIndex++)
  {
    if (aRxBuffer[uwIndex] != aTxBuffer[uwIndex])
    {
      uwWriteReadStatus++;
    }
  }	

  if (uwWriteReadStatus)
  {
    /* KO */
    /* Turn on LED4 */
		LED_On(0);//绿灯
//    BSP_LED_On(LED4);     
  }
  else
  { 
    /* OK */
    /* Turn on LED3 */
		LED_On(1);//红灯
//    BSP_LED_On(LED3);
  }
//			LED_On(0);
//		 	BSP_SDRAM_Init();//初始化SDRAM
//			BSP_SDRAM_WriteData(SDRAM_DEVICE_ADDR,&data_test,1);//写数据
//			BSP_SDRAM_ReadData(SDRAM_DEVICE_ADDR,&data_test_rec,1);//读数据
//			if(data_test == data_test_rec)
//			{
//					LED_On(1);
//			}
#endif

#ifdef RTE_CMSIS_RTOS                   // when using CMSIS RTOS
  // create 'thread' functions that start executing,
  // example: tid_name = osThreadCreate (osThread(name), NULL);

  osKernelStart();                      // start thread execution 
#endif

  /* Infinite loop */
  while (1)
  {
  }

}

/**
  * @brief  System Clock Configuration
  *         The system Clock is configured as follow : 
  *            System Clock source            = PLL (HSE)
  *            SYSCLK(Hz)                     = 168000000
  *            HCLK(Hz)                       = 168000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 4
  *            APB2 Prescaler                 = 2
  *            HSE Frequency(Hz)              = 8000000
  *            PLL_M                          = 8
  *            PLL_N                          = 336
  *            PLL_P                          = 2
  *            PLL_Q                          = 7
  *            VDD(V)                         = 3.3
  *            Main regulator output voltage  = Scale1 mode
  *            Flash Latency(WS)              = 5
  * @param  None
  * @retval None
  */
static void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;
  
  /* Enable Power Control clock */
  __HAL_RCC_PWR_CLK_ENABLE();
  
  /* The voltage scaling allows optimizing the power consumption when the device is 
     clocked below the maximum system frequency, to update the voltage scaling value 
     regarding system frequency refer to product datasheet.  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /* Enable HSE Oscillator and activate PLL with HSE as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 360;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }
  
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;  
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }

  /* STM32F405x/407x/415x/417x Revision Z devices: prefetch is supported  */
  if (HAL_GetREVID() == 0x1001)
  {
    /* Enable the Flash prefetch */
    __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
  }
}
/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
static void Error_Handler(void)
{
  /* User may add here some code to deal with this error */
  while(1)
  {
  }
}



#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

/**
  * @}
  */ 

/**
  * @}
  */ 

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

调试程序

在cmd_format函数中添加断点,观察是否会进入格式化成功的逻辑中

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值