今天是学习STM32MP157C的8第三天,研究在STM32CubeIDE 下如何开发M4的应用程序.
遇到的一些问题.
IDE和MX的切换
双击击项目最后的.ioc 文件,出现CubeMX的窗口。 保存这个文件,自动产生程序,并回到IDE.
定义GPIO端口
由于GPIO 可以在两个处理器上定义,因此,需要对着引脚击右键,设置Pin Reservied 选择M4.否则,相应的GPIO 代码不出现。
我在程序中定义了开发板的红灯和蓝灯,他们分别是
PA13 -LED_RED
PA14 - LED_BLUE
openAMP
openAMP 是一个中间件,它的低层是IPCC 所以要现将System Core 中的PICC 参数中打钩的地方全部打钩。然后在中间件目录下打开openAMP 。和米尔文档中的例子不同。下面的程序已经包含在openAMP 中间件中了。
- mbox_ipcc.c
- openamp,c
- openamp.log,c
- res_table.c
UART
UART 是从UART4 开始的。大概前面三个都分配给了A7了吧?我想使用UART4 输出M4 的Printf 信息。不知道是否会冲突?
fw_cortex_m4.sh
这个文件自动产生了,包含在RemoteProc目录中。
主程序
我建立了一个test项目,并参照了OpenAMP_TTY_echo 项目中的主程序,修改了我的主程序。
main.c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "openamp.h"
#include "virt_uart.h"
#include "openamp_log.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#define MAX_BUFFER_SIZE RPMSG_BUFFER_SIZE
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
IPCC_HandleTypeDef hipcc;
/* USER CODE BEGIN PV */
VIRT_UART_HandleTypeDef huart0;
VIRT_UART_HandleTypeDef huart1;
__IO FlagStatus VirtUart0RxMsg = RESET;
uint8_t VirtUart0ChannelBuffRx[MAX_BUFFER_SIZE];
uint16_t VirtUart0ChannelRxSize = 0;
__IO FlagStatus VirtUart1RxMsg = RESET;
uint8_t VirtUart1ChannelBuffRx[MAX_BUFFER_SIZE];
uint16_t VirtUart1ChannelRxSize = 0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_IPCC_Init(void);
int MX_OPENAMP_Init(int RPMsgRole, rpmsg_ns_bind_cb ns_bind_cb);
/* USER CODE BEGIN PFP */
void VIRT_UART0_RxCpltCallback(VIRT_UART_HandleTypeDef *huart);
void VIRT_UART1_RxCpltCallback(VIRT_UART_HandleTypeDef *huart);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
if(IS_ENGINEERING_BOOT_MODE())
{
/* Configure the system clock */
SystemClock_Config();
}
/* IPCC initialisation */
MX_IPCC_Init();
/* OpenAmp initialisation ---------------------------------*/
MX_OPENAMP_Init(RPMSG_REMOTE, NULL);
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
log_info("Virtual UART0 OpenAMP-rpmsg channel creation\r\n");
if (VIRT_UART_Init(&huart0) != VIRT_UART_OK) {
log_err("VIRT_UART_Init UART0 failed.\r\n");
Error_Handler();
}
log_info("Virtual UART1 OpenAMP-rpmsg channel creation\r\n");
if (VIRT_UART_Init(&huart1) != VIRT_UART_OK) {
log_err("VIRT_UART_Init UART1 failed.\r\n");
Error_Handler();
}
/*Need to register callback for message reception by channels*/
if(VIRT_UART_RegisterCallback(&huart0, VIRT_UART_RXCPLT_CB_ID, VIRT_UART0_RxCpltCallback) != VIRT_UART_OK)
{
Error_Handler();
}
if(VIRT_UART_RegisterCallback(&huart1, VIRT_UART_RXCPLT_CB_ID, VIRT_UART1_RxCpltCallback) != VIRT_UART_OK)
{
Error_Handler();
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
OPENAMP_check_for_message();
/* USER CODE END WHILE */
if (VirtUart0RxMsg) {
VirtUart0RxMsg = RESET;
VIRT_UART_Transmit(&huart0, VirtUart0ChannelBuffRx, VirtUart0ChannelRxSize);
}
if (VirtUart1RxMsg) {
VirtUart1RxMsg = RESET;
VIRT_UART_Transmit(&huart1, VirtUart1ChannelBuffRx, VirtUart1ChannelRxSize);
}
// HAL_GPIO_WritePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin, GPIO_PIN_SET);
// HAL_Delay(1000);
// HAL_GPIO_WritePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin, GPIO_PIN_RESET);
// HAL_Delay(1000);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.HSIDivValue = RCC_HSI_DIV1;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
RCC_OscInitStruct.PLL2.PLLState = RCC_PLL_NONE;
RCC_OscInitStruct.PLL3.PLLState = RCC_PLL_NONE;
RCC_OscInitStruct.PLL4.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** RCC Clock Config
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_ACLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_PCLK3|RCC_CLOCKTYPE_PCLK4
|RCC_CLOCKTYPE_PCLK5;
RCC_ClkInitStruct.AXISSInit.AXI_Clock = RCC_AXISSOURCE_HSI;
RCC_ClkInitStruct.AXISSInit.AXI_Div = RCC_AXI_DIV1;
RCC_ClkInitStruct.MCUInit.MCU_Clock = RCC_MCUSSOURCE_HSI;
RCC_ClkInitStruct.MCUInit.MCU_Div = RCC_MCU_DIV1;
RCC_ClkInitStruct.APB4_Div = RCC_APB4_DIV1;
RCC_ClkInitStruct.APB5_Div = RCC_APB5_DIV1;
RCC_ClkInitStruct.APB1_Div = RCC_APB1_DIV1;
RCC_ClkInitStruct.APB2_Div = RCC_APB2_DIV1;
RCC_ClkInitStruct.APB3_Div = RCC_APB3_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief IPCC Initialization Function
* @param None
* @retval None
*/
static void MX_IPCC_Init(void)
{
/* USER CODE BEGIN IPCC_Init 0 */
/* USER CODE END IPCC_Init 0 */
/* USER CODE BEGIN IPCC_Init 1 */
/* USER CODE END IPCC_Init 1 */
hipcc.Instance = IPCC;
if (HAL_IPCC_Init(&hipcc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN IPCC_Init 2 */
/* USER CODE END IPCC_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pins : LED_BLUE_Pin LED_RED_Pin */
GPIO_InitStruct.Pin = LED_BLUE_Pin|LED_RED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
void VIRT_UART0_RxCpltCallback(VIRT_UART_HandleTypeDef *huart)
{
log_info("Msg received on VIRTUAL UART0 channel: %s \n\r", (char *) huart->pRxBuffPtr);
/* copy received msg in a variable to sent it back to master processor in main infinite loop*/
VirtUart0ChannelRxSize = huart->RxXferSize < MAX_BUFFER_SIZE? huart->RxXferSize : MAX_BUFFER_SIZE-1;
memcpy(VirtUart0ChannelBuffRx, huart->pRxBuffPtr, VirtUart0ChannelRxSize);
VirtUart0RxMsg = SET;
}
void VIRT_UART1_RxCpltCallback(VIRT_UART_HandleTypeDef *huart)
{
log_info("Msg received on VIRTUAL UART1 channel: %s \n\r", (char *) huart->pRxBuffPtr);
/* copy received msg in a variable to sent it back to master processor in main infinite loop*/
VirtUart1ChannelRxSize = huart->RxXferSize < MAX_BUFFER_SIZE? huart->RxXferSize : MAX_BUFFER_SIZE-1;
memcpy(VirtUart1ChannelBuffRx, huart->pRxBuffPtr, VirtUart1ChannelRxSize);
VirtUart1RxMsg = SET;
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#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 CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
测试
测试方法与前一篇博文介绍差不多。
这次直接在workspace 中建立了lib 文件夹,在lib 下面建立了firmware 文件夹 将fw_cortex_cortex_m4.sh 传送到workspace
scp fw_cortex_m4.sh root@192.168.31.194://home/root/workspace
fw_cortex_m4.sh 100% 541 0.5KB/s 00:00
将test_CM4.elf 传送到 lib/firmware 中
(base) yao@yao-dc:~/STM32CubeIDE/workspace_1.4.0/test/CM4/Release$ scp test_CM4.elf root@192.168.31.194:/home/root/workspace/lib/firmware
test_CM4.elf 100% 217KB 216.7KB/s 00:00
使用 ssh root@192.168.31.194 进入开发板linux
root@myir:~/workspace# ./fw_cortex_m4.sh start
root@myir:~/workspace# stty -onlcr -echo -F /dev/ttyRPMSG0
root@myir:~/workspace# cat /dev/ttyRPMSG0 &
root@myir:~/workspace# stty -onlcr -echo -F /dev/ttyRPMSG1
root@myir:~/workspace# cat /dev/ttyRPMSG1 &
root@myir:~/workspace# echo "hello virtual UART0" >/dev/ttyRPMSG0
root@myir:~/workspace# hello virtual UART0
root@myir:~/workspace# echo "hello virtual UART1" >/dev/ttyRPMSG1
root@myir:~/workspace# hello virtual UART1
同时可以看到开发板上的红灯闪烁,如果键入./fw_cortex_m4.sh stop 红灯停止,表示M4 固件停止运行。
A7/linux 端测试程序
晚上,编写了 A7/linux 端测试程序
#include <stdio.h>
#include <iostream>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cstring>
// compiller $CC testAMP.cpp -o test -lstdc++
//source SDK/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
using namespace std;
const char* rxBuf="Hello M4";
char* txBuf;
int main(void){
cout<< "openAMP test"<<endl;
int fd = open("/dev/ttyRPMSG0", O_RDWR);
int len=strlen(rxBuf);
write(fd, rxBuf, len);
txBuf=new char(len);
read(fd,txBuf,len);
string msg=txBuf;
cout<<"msg from M4:"<<msg<<endl;
return 0;
}