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
    评论
### 回答1: Keil MDK是一款嵌入式开发工具,它提供了丰富的功能和易用的界面,可以帮助开发人员进行嵌入式软件的开发和调试。其中的编辑器配色文件是指可以修改编辑器的颜色方案,以满足开发人员个性化的需求。 要修改Keil MDK编辑器的配色方案,首先需要打开Keil MDK软件,然后点击菜单栏中的"Options"选项,再选择"Fonts and Colors"。接着,在弹出的窗口中,可以看到各种不同语言的配色选项。 点击对应的语言选项,比如C、C++、ASM等,就可以设置该语言的配色方案。在配色方案窗口中,可以设置编辑器的前景色和背景色,以及关键字、注释、字符串等的颜色。通过选择不同的颜色,并进行预览,可以实时查看效果。还可以根据自己的喜好,调整配色方案的亮度、对比度等参数。 在选择配色方案后,点击"Apply"按钮,就可以将修改的配色方案应用到Keil MDK的编辑器中了。如果想要保存修改的配色方案,可以点击"Save"按钮,然后给配色方案命名,并保存到指定的位置。 通过修改Keil MDK编辑器的配色方案,可以使开发人员在编写代码时更加舒适和高效。不同的颜色搭配和亮度对比可以帮助开发人员更好地区分不同的代码元素,提高代码的可读性和可维护性。因此,根据个人喜好和需求,合理设置Keil MDK编辑器的配色方案是很重要的。 ### 回答2: Keil MDK(Microcontroller Development Kit)编辑器是一种常用的嵌入式开发工具,用于编写和调试嵌入式系统的程序代码。配色文件可以用来改变编辑器界面的颜色和外观,以提高开发者的舒适度和工作效率。 在Keil MDK编辑器中,我们可以根据自己的喜好和需求进行配色定制。一般而言,配色文件是以XML格式保存的,可以包含各种编辑器界面的颜色和样式设置。 要更改Keil MDK编辑器的配色,可以按照以下步骤进行: 1. 打开Keil MDK编辑器,并在菜单栏中选择“Options”(选项)。 2. 在弹出的对话框中,选择“Editor”(编辑器)选项。 3. 在编辑器选项中,可以找到“Colors”(颜色)选项。在这里,可以看到各种编辑器元素(如关键字、注释、字符串等)的配色设置。 4. 可以通过单击下拉菜单来选择不同的配色方案。通常,Keil MDK提供了一些预定义的配色方案,如“Classic”(经典)、“Dark”(暗黑)等。 5. 如果需要进行自定义配色,可以单击“Edit...”按钮来编辑配色方案。在弹出的对话框中,可以更改具体的颜色值和样式设置。 6. 编辑完成后,点击“OK”按钮保存并应用新的配色方案。 需要注意的是,更改配色文件可能需要重启Keil MDK编辑器才能生效。此外,Keil MDK还提供了其他一些编辑器设置,如字体、缩进、代码折叠等,可以根据个人习惯进行调整。 通过改变Keil MDK编辑器的配色文件,可以让开发者在编写和调试嵌入式程序时有一个更舒适和高效的工作环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值