My question is simple, I just want to send 20 bytes of data from a STM32F103C8 blue phill card in i2c slave mode to a raspberry pi 3 in master mode, I use STM32Cube IDE can any other IDE work for me. After browsing the web, I don't fully understand everything necessary for this. Thank you,
I add source code that I am testing, at the moment it does not work for me and I want to know what may be wrong,
#include "main.h"
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
//#define MASTER_BOARD
#define I2C_ADDRESS 0x30F
#define RXBUFFERSIZE 20
/* USER CODE END PD */
//#define I2C_SPEEDCLOCK 100000
#define I2C_DUTYCYCLE I2C_DUTYCYCLE_2
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
/* USER CODE BEGIN PV */
uint8_t aTxBuffer[] = " ****I2C_TwoBoards communication based on IT**** ****I2C_TwoBoards communication based on IT**** ";
uint8_t aRxBuffer[RXBUFFERSIZE];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
/* USER CODE BEGIN PFP */
int main(void) {
/* USER CODE BEGIN 1 */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
if (HAL_I2C_Init(&I2cHandle) != HAL_OK) {
/* Initialization Error */
Error_Handler();
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
if(HAL_I2C_Slave_Receive_IT(&I2cHandle, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)
{
/* Transfer error in reception process */
Error_Handler();
}
//**************************************************************************************************
while (HAL_I2C_GetState(&I2cHandle) != HAL_I2C_STATE_READY)
{
}
//**************************************************************************************************
if(HAL_I2C_Slave_Transmit_IT(&I2cHandle, (uint8_t*)aTxBuffer, TXBUFFERSIZE)!= HAL_OK)
{
/* Transfer error in transmission process */
Error_Handler();
}
//**************************************************************************************************
while (HAL_I2C_GetState(&I2cHandle) != HAL_I2C_STATE_READY)
{
}
//**************************************************************************************************
if(Buffercmp((uint8_t*)aTxBuffer,(uint8_t*)aRxBuffer,RXBUFFERSIZE))
{
/* Processing Error */
Error_Handler();
}
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
Error_Handler();
}
}
/**
* #brief I2C1 Initialization Function
* #param None
* #retval None
*/
static void MX_I2C1_Init(void) {
/* USER CODE BEGIN I2C1_Init 0 */
/* USER CODE END I2C1_Init 0 */
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
static void MX_GPIO_Init(void) {
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
}
/* USER CODE BEGIN 4 */
/* 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****/
The question is broad so I will answer about the methodology to solve this kind of problems.
Try to narrow this down into smaller steps, each step could be broken down to smaller steps or even generate new questions here.
find a STM32 I2C slave example, build and flash it.
how to run a blinky example on STM32
how to open i2c port
connect your oscilloscope and observe output
read any data from RPi
Can you read data from a known good slave?
connect the devices
modify slave code to send custom data.
write the application on your raspberry pi
Related
I have some functions to read-and write to memory to STM32F103 internal memory. This functions work on the gcc and standard linker script. When I want to use the internal flash with stm32 and freertos. FreeRtos does not allow to me access when I want to write a data into internal flash. Here is the standard freertos linker script file.
Default linker script file for freertos for stm32.
/*************************************************
* linker script for ST32F103 & MPU REV 1.02
************************************************/
GROUP(libgcc.a libc.a)
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
}
/* Higher address of the user mode stack */
_estack = ORIGIN(SRAM)+LENGTH(SRAM);
/*
*There will be a link error if there is not this amount of RAM free at the end.
*/
_Minimum_Stack_Size = 1K;
_Minimum_Heap_Size = 1K;
/* Variables used by FreeRTOS-MPU. */
_Privileged_Functions_Region_Size = 16K;
_Privileged_Data_Region_Size = 512;
__FLASH_segment_start__ = ORIGIN( FLASH );
__FLASH_segment_end__ = __FLASH_segment_start__ + LENGTH( FLASH );
__privileged_functions_start__ = ORIGIN( FLASH );
__privileged_functions_end__ = __privileged_functions_start__ + _Privileged_Functions_Region_Size;
__SRAM_segment_start__ = ORIGIN( SRAM );
__SRAM_segment_end__ = __SRAM_segment_start__ + LENGTH( SRAM );
__privileged_data_start__ = ORIGIN( SRAM );
__privileged_data_end__ = ORIGIN( SRAM ) + _Privileged_Data_Region_Size;
ENTRY(Reset_Handler)
SECTIONS
{
/*
Privileged section at the start of the flash.
Vectors must be first whatever.
*/
.isr_vectors :
{
. = ALIGN(4);
_isr_vectors_offs = . - __FLASH_segment_start__;
KEEP(*(.isr_vectors)) /* Startup code */
} >FLASH
privileged_functions :
{
. = ALIGN(4);
*(privileged_functions)
} > FLASH
/* Non privileged code starts here. */
.text_offset :
{
. = ALIGN(4);
. = . + _Privileged_Functions_Region_Size;
} > FLASH
.text :
{
. = ALIGN(4);
*(.text) /* remaining code */
*(.text.*) /* remaining code */
*(.rodata) /* read-only data (constants) */
*(.rodata*)
*(.glue_7)
*(.glue_7t)
} > FLASH
/*
.ARM.exidx is sorted, so has to go in its own output section.
*/
. = ALIGN(4);
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} >FLASH
__exidx_end = .;
/* -- */
.data.align :
{
. = ALIGN(4);
_etext = .;
_sipdata = _etext; /* Used by the startup in order to initialize privileged variables */
} >FLASH
/* -- */
.pdata.align :
{
. = ALIGN(4);
. = . + _Privileged_Data_Region_Size;
_sidata = .; /* Used by the startup in order to initialize variables */
} >FLASH
/*
* This is the Privileged data section. It is stored in RAM but the initial values
* are held in flash and copied to RAM by the startup code
*/
privileged_data : AT ( _sipdata ) /* AT makes the LMA follow on in the binary image */
{
. = ALIGN(4);
_bss = .;
_spdata = . ;
*(privileged_data)
_epdata = . ;
} > SRAM
/*
* This is the initialized data section. It is stored in RAM but the initial values
* are held in flash and copied to RAM by the startup code
*/
.data_offset :
{
. = ALIGN(4);
. = . + _Privileged_Data_Region_Size;
} > SRAM
.data : AT ( _sidata ) /* AT makes the LMA follow on in the binary image */
{
_sdata = . ; /* Used by the startup in order to initialize the .data section */
KEEP(*(vtable))
KEEP( *(.data) )
KEEP( *(.data.*) )
. = ALIGN(4);
_edata = . ; /* Used by the startup in order to initialize the .data section */
} >SRAM
/*
* This is the uninitialized data section. Date here is stored in RAM and will be
* set to zero by the startup code.
*/
.bss :
{
. = ALIGN(4);
_sbss = .; /* Used by the startup in order to initialize the .bss section */
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ; /* Used by the startup in order to initialize the .bss section */
} >SRAM
/*
* This is the heap section
* This is just to check that there is enough RAM left for the heap
* It should generate an error if it's full.
*/
._sheap :
{
. = ALIGN(4);
_heap_begin = . ;
. = . + _Minimum_Heap_Size ;
. = ALIGN(4);
_heap_end = . ;
} >SRAM
/*
* This is the user stack section
* This is just to check that there is enough RAM left for the User mode stack
* It should generate an error if it's full.
*/
._usrstack :
{
. = ALIGN(4);
_susrstack = . ;
. = . + _Minimum_Stack_Size ;
. = ALIGN(4);
_eusrstack = . ;
} >SRAM
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
PROVIDE( _heap = _heap_begin );
PROVIDE ( _eheap = _heap_end );
}
and here is the my new linker script file here to access the last page of the stm32f103 which is page 255. When I want to modify the page255. It does not allow me. Do you have suggestion that how can use the internal flash of the stm32 with freertos? I just need to use one page in the flash when freertos in the usage. Everything works if I do not use freertos
/*************************************************
* linker script for ST32F103 & MPU REV 1.02
************************************************/
GROUP(libgcc.a libc.a)
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1022K
FLASH_STORAGE (rwx) : ORIGIN = 0x08000000+1022K, LENGTH = 2K
SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
}
/* Higher address of the user mode stack */
_estack = ORIGIN(SRAM)+LENGTH(SRAM);
/*
*There will be a link error if there is not this amount of RAM free at the end.
*/
_Minimum_Stack_Size = 1K;
_Minimum_Heap_Size = 1K;
/* Variables used by FreeRTOS-MPU. */
_Privileged_Functions_Region_Size = 16K;
_Privileged_Data_Region_Size = 512;
__FLASH_segment_start__ = ORIGIN( FLASH );
__FLASH_segment_end__ = __FLASH_segment_start__ + LENGTH( FLASH );
__privileged_functions_start__ = ORIGIN( FLASH );
__privileged_functions_end__ = __privileged_functions_start__ + _Privileged_Functions_Region_Size;
__SRAM_segment_start__ = ORIGIN( SRAM );
__SRAM_segment_end__ = __SRAM_segment_start__ + LENGTH( SRAM );
__privileged_data_start__ = ORIGIN( SRAM );
__privileged_data_end__ = ORIGIN( SRAM ) + _Privileged_Data_Region_Size;
ENTRY(Reset_Handler)
SECTIONS
{
/*
Privileged section at the start of the flash.
Vectors must be first whatever.
*/
.isr_vectors :
{
. = ALIGN(4);
_isr_vectors_offs = . - __FLASH_segment_start__;
KEEP(*(.isr_vectors)) /* Startup code */
} >FLASH
privileged_functions :
{
. = ALIGN(4);
*(privileged_functions)
} > FLASH
/* Non privileged code starts here. */
.text_offset :
{
. = ALIGN(4);
. = . + _Privileged_Functions_Region_Size;
} > FLASH
.text :
{
. = ALIGN(4);
*(.text) /* remaining code */
*(.text.*) /* remaining code */
*(.rodata) /* read-only data (constants) */
*(.rodata*)
*(.glue_7)
*(.glue_7t)
} > FLASH
/*
.ARM.exidx is sorted, so has to go in its own output section.
*/
. = ALIGN(4);
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} >FLASH
__exidx_end = .;
/* -- */
.data.align :
{
. = ALIGN(4);
_etext = .;
_sipdata = _etext; /* Used by the startup in order to initialize privileged variables */
} >FLASH
/* -- */
.pdata.align :
{
. = ALIGN(4);
. = . + _Privileged_Data_Region_Size;
_sidata = .; /* Used by the startup in order to initialize variables */
} >FLASH
/*
* This is the Privileged data section. It is stored in RAM but the initial values
* are held in flash and copied to RAM by the startup code
*/
privileged_data : AT ( _sipdata ) /* AT makes the LMA follow on in the binary image */
{
. = ALIGN(4);
_bss = .;
_spdata = . ;
*(privileged_data)
_epdata = . ;
} > SRAM
/*
* This is the initialized data section. It is stored in RAM but the initial values
* are held in flash and copied to RAM by the startup code
*/
.data_offset :
{
. = ALIGN(4);
. = . + _Privileged_Data_Region_Size;
} > SRAM
.data : AT ( _sidata ) /* AT makes the LMA follow on in the binary image */
{
_sdata = . ; /* Used by the startup in order to initialize the .data section */
KEEP(*(vtable))
KEEP( *(.data) )
KEEP( *(.data.*) )
. = ALIGN(4);
_edata = . ; /* Used by the startup in order to initialize the .data section */
} >SRAM
/*
* This is the uninitialized data section. Date here is stored in RAM and will be
* set to zero by the startup code.
*/
.bss :
{
. = ALIGN(4);
_sbss = .; /* Used by the startup in order to initialize the .bss section */
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ; /* Used by the startup in order to initialize the .bss section */
} >SRAM
/*
* This is the heap section
* This is just to check that there is enough RAM left for the heap
* It should generate an error if it's full.
*/
._sheap :
{
. = ALIGN(4);
_heap_begin = . ;
. = . + _Minimum_Heap_Size ;
. = ALIGN(4);
_heap_end = . ;
} >SRAM
/*
* This is the user stack section
* This is just to check that there is enough RAM left for the User mode stack
* It should generate an error if it's full.
*/
._usrstack :
{
. = ALIGN(4);
_susrstack = . ;
. = . + _Minimum_Stack_Size ;
. = ALIGN(4);
_eusrstack = . ;
} >SRAM
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
PROVIDE( _heap = _heap_begin );
PROVIDE ( _eheap = _heap_end );
}
The changes are from this linker script
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
}
to this linker script:
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1022K
FLASH_STORAGE (rwx) : ORIGIN = 0x08000000+1022K, LENGTH = 2K
SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
}
Here is the my codes to write the flash with FreeRtos.
flash.c file.
#include <FreeRTOS.h>
#include <queue.h>
#include <task.h>
/* -- */
#include "FlashMemoryDataStorage_FreeRtos.h"
/* -- */
/********************************************************************************
; Function: FlashMemoryDataStorage_UnLock
;
; Description: unlocks the flash memory
;
; Inputs: nothing
;
; Returns: Nothing
*********************************************************************************/
void FlashMemoryDataStorage_UnLock(void)
{
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
/********************************************************************************
; Function: FlashMemoryDataStorage_Lock
;
; Description: locks the flash memory
;
; Inputs: nothing
;
; Returns: Nothing
*********************************************************************************/
void FlashMemoryDataStorage_Lock(void)
{
FLASH->CR = FLASH_CR_LOCK;
}
/*********************************************************************************
; Function: FlashMemoryDataStorage_SectorErase
;
; Description: erases a sector
;
; Inputs: uint32_t address of erase operation
;
; Returns: Nothing
*********************************************************************************/
void FlashMemoryDataStorage_SectorErase(uint32_t addr)
{
FlashMemoryDataStorage_UnLock();
/* -- */
FLASH->CR |= FLASH_CR_PER;
FLASH->CR &= ~FLASH_CR_PG;
FLASH->CR |= FLASH_CR_OPTER;
FLASH->AR = addr;
FLASH->CR |= FLASH_CR_STRT;
/* wait until the operation finish */
while(FLASH->SR & (uint32_t)FLASH_SR_BSY);
FLASH->CR &= ~(FLASH_CR_PER | FLASH_CR_OPTER);
/* -- */
FlashMemoryDataStorage_Lock();
}
/*********************************************************************************
; Function: FlashMemoryDataStorage_SectorWrite
;
; Description: writes a sector
;
; Inputs: uint32_t address of write operation
;
; Inputs: uint32_t address of write buffer
;
; Returns: Nothing
*********************************************************************************/
ERRCODE FlashMemoryDataStorage_SectorWrite(uint32_t addr,void * pBuff)
{
ERRCODE ec = SUCCESS;
uint16_t size=0, *pAddr=NULL, *pBuffTemp=NULL;
/* -- */
size = FLASH_SECTOR_SIZE;
pAddr = (uint16_t *)addr;
pBuffTemp =(uint16_t *)pBuff;
size = size / 2; /* incoming values are in bytes (It should be 16-bit) */
/* -- */
while(size) {
FlashMemoryDataStorage_UnLock();
/* -- */
FLASH->CR &= ~FLASH_CR_PER;
FLASH->CR |= FLASH_CR_PG;
*(pAddr) = *(pBuffTemp);
tprintf("\r\nPage Erased22: \r\n");
while(1);
/* wait until the operation finish */
while(FLASH->SR & FLASH_SR_BSY);
if (FLASH->SR & FLASH_SR_PGERR) {
ec = FLASH_WRITE_PAGE_ERR;
tprintf("PAGE ERR");
while(1);
goto func_end;
}
/* -- */
if (FLASH->SR & FLASH_SR_WRPRTERR) {
ec = FLASH_WRITE_PROTECTION_ERR;
tprintf("WRTIE PROTEC");
while(1);
goto func_end;
}
pAddr++;
pBuffTemp++;
size--;
}
/* -- */
func_end:
FlashMemoryDataStorage_Lock();
return ec;
}
/*********************************************************************************************
; Function: FlashMemoryDataStorage_SectorDump
;
; Description: dumps a sector
;
; Inputs: uint32_t starting address of dump operation
;
; Returns: Nothing
***********************************************************************************************/
void FlashMemoryDataStorage_SectorDump(uint32_t addr)
{
uint16_t ndx=0, size=0;
size = FLASH_SECTOR_SIZE;
for( ndx=0; ndx < size; ndx++){
if(!(ndx % 16)) tprintf("\n\r0x%04x",ndx);
tprintf(" %02x",*(char *)addr);
addr++;
}
}
/*********************************************************************************************
; Function: FlashMemoryDataStorage_SectorRead
;
; Description: reads a sector
;
; Inputs: uint32_t starting address of read operation
;
; Inputs: char * read buffer pointer
;
; Returns: Nothing
;
***********************************************************************************************/
void FlashMemoryDataStorage_SectorRead(uint32_t addr, char *pBuff)
{
uint16_t index=0, size=0;
size = FLASH_SECTOR_SIZE;
for( index=0; index < size; index++){
pBuff[index] = *(char *)addr;
addr++;
}
}
/*********************************************************************************************
; Function: FlashMemoryDataStorage_SectorFillBuffer
;
; Description: fills the memory with a character
;
; Inputs: char * buffer pointer
;
; Inputs: char chacacter to fill
;
; Returns: Nothing
;
***********************************************************************************************/
void FlashMemoryDataStorage_SectorFillBuffer(char *pBuff, char ch)
{
uint16_t ndx=0, size=0;
size = FLASH_SECTOR_SIZE;
for( ndx=0; ndx < size; ndx++){
pBuff[ndx] = ch;
}
}
/* -- */
static void vTest_Flash( void *pvParameters )
{
/* The parameters are not used in this function. */
(void) pvParameters;
char buffw[FLASH_SECTOR_SIZE];
char buffr[FLASH_SECTOR_SIZE];
while(1) {
/* Erase Memory */
tprintf("\r\nPage Erased: \r\n");
FlashMemoryDataStorage_SectorErase(PAGE_255_ADDR);
/* sector 1 write operation */
FlashMemoryDataStorage_SectorFillBuffer(buffw,'a');
FlashMemoryDataStorage_SectorWrite(PAGE_255_TEST_SECTOR1,buffw);
FlashMemoryDataStorage_SectorRead(PAGE_255_TEST_SECTOR1,buffr);
if(0 != memcmp(buffw,buffr,FLASH_SECTOR_SIZE)) {
tprintf("\r\n flash read/error %d",PAGE_255_TEST_SECTOR1);
}
/* sector dump operations */
/* sector1 dump */
tprintf("\r\nSector 1 Dump: \r\n");
FlashMemoryDataStorage_SectorDump(PAGE_255_TEST_SECTOR1);
vTaskDelay(30000);;
}
}
/* -- */
int main()
{
portBASE_TYPE xReturn;
/* -- */
xReturn = xTaskCreate ( vTest_Flash, ( const signed portCHAR * const )"Test_Flash", configMINIMAL_STACK_SIZE<<5, NULL, tskIDLE_PRIORITY, NULL );
if( xReturn != pdPASS ) {
tprintf("\n\rTest_Flash initilisation problem.\n\r");
}
/* Now all the tasks have been started - start the scheduler. */
vTaskStartScheduler();
return 0;
}
flash.h file
/* -- */
#define FLASH_KEY1 0x45670123 /* These Values Come From PM0075(Programming Manual Section 2.3.1) */
#define FLASH_KEY2 0xCDEF89AB /* We Need To Set The Keys Sequentialy As Described In PM0075 */
/* -- */
#define FLASH_SECTOR_SIZE 128
/* -- */
#define FLASH_WRITE_PAGE_ERR 0x40
#define FLASH_WRITE_PROTECTION_ERR 0x41
/* -- */
#define PAGE_255_ADDR 0x0807F800
#define PAGE_255_TEST_SECTOR1 PAGE_255_ADDR
#define PAGE_255_TEST_SECTOR2 (PAGE_255_TEST_SECTOR1 + 0x200)
#define PAGE_255_TEST_SECTOR3 (PAGE_255_TEST_SECTOR2 + 0x200)
#define PAGE_255_TEST_SECTOR4 (PAGE_255_TEST_SECTOR3 + 0x200)
/* -- */
void FlashMemoryDataStorage_UnLock(void);
void FlashMemoryDataStorage_Lock(void);
void FlashMemoryDataStorage_SectorErase(uint32_t addr);
void FlashMemoryDataStorage_SectorRead(uint32_t addr, char *pBuff);
ERRCODE FlashMemoryDataStorage_SectorWrite(uint32_t addr,void * pBuff);
/* -- */
I am using an STM32F429 device for CAN polling transmitting and receiving messages.
I have used part of the "STM32Cube_FW_F4_V1.21.0" LOOPBACK example. By difference I have turned loopback mode to normal mode.
I can transmit messages successfully, but I can not receive any message. I am transmitting CAN messages with Id=0x22 with another device to STM32F429, but it can not receive them and FIFO level is always zero. Here is the code:
/* Includes -------------------------------------------------------- */
#include "main.h"
#include "stm32f4xx_hal.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private variables ----------------------------------------------- */
CAN_HandleTypeDef hcan1;
/* USER CODE BEGIN PV */
/* Private variables ----------------------------------------------- */
/* USER CODE END PV */
/* Private function prototypes ------------------------------------- */
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN1_Init(void);
void Can_Transmit();
void Can_Recieve();
CAN_HandleTypeDef CanHandle;
CAN_TxHeaderTypeDef TxHeader;
CAN_RxHeaderTypeDef RxHeader;
uint8_t TxData[8];
uint8_t RxData[8];
uint32_t TxMailbox;
uint32_t RcvData = 0;
uint32_t td = 0x67;
uint8_t ERR = 0;
/* USER CODE BEGIN PFP */
/* Private function prototypes ------------------------------------- */
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* #brief The application entry point.
*
* #retval None
*/
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 */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_CAN1_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if (HAL_CAN_GetRxFifoFillLevel(&CanHandle, CAN_RX_FIFO0) != 1)
{
/* Reception Missing */
Error_Handler();
}
if (HAL_CAN_GetRxMessage(&CanHandle, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
{
/* Reception Error */
Error_Handler();
}
if (RxHeader.StdId == 0x22)
RcvData = ((RxData[1]<<8) | RxData[0]);
}
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/** Configure the main internal regulator output voltage */
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the CPU, AHB and APB busses clocks */
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 = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/** Initializes the CPU, AHB and APB busses clocks */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|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)
{
_Error_Handler(__FILE__, __LINE__);
}
/** Configure the Systick interrupt time */
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/** Configure the Systick */
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/* CAN1 init function */
static void MX_CAN1_Init(void)
{
CAN_FilterTypeDef sFilterConfig;
/* ## -1- Configure the CAN peripheral ########################### */
CanHandle.Instance = CAN1;
CanHandle.Init.TimeTriggeredMode = DISABLE;
CanHandle.Init.AutoBusOff = DISABLE;
CanHandle.Init.AutoWakeUp = DISABLE;
CanHandle.Init.AutoRetransmission = ENABLE;
CanHandle.Init.ReceiveFifoLocked = DISABLE;
CanHandle.Init.TransmitFifoPriority = DISABLE;
CanHandle.Init.Mode = CAN_MODE_NORMAL;
CanHandle.Init.SyncJumpWidth = CAN_SJW_1TQ;
CanHandle.Init.TimeSeg1 = CAN_BS1_4TQ;
CanHandle.Init.TimeSeg2 = CAN_BS2_2TQ;
CanHandle.Init.Prescaler = 12;
if (HAL_CAN_Init(&CanHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/* ## -2- Configure the CAN Filter ############################### */
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.SlaveStartFilterBank = 14;
if (HAL_CAN_ConfigFilter(&CanHandle, &sFilterConfig) != HAL_OK)
{
/* Filter configuration Error */
Error_Handler();
}
/* ## -3- Start the CAN peripheral ############################### */
if (HAL_CAN_Start(&CanHandle) != HAL_OK)
{
/* Start Error */
Error_Handler();
}
}
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
static void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* #brief This function is executed in case of error occurrence.
* #param file: The file name as string.
* #param line: The line in file as a number.
* #retval None
*/
void _Error_Handler(char *file, int line)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL
error return state */
while(1){
}
/* USER CODE END Error_Handler_Debug */
}
If this is still active, try sth. like this:
//set filter / mask to accept every identifier
CAN_FilterTypeDef filter = {0};
filter.FilterIdHigh = 0x1fff;
filter.FilterIdLow = 0xffff;
filter.FilterMaskIdHigh = 0;
filter.FilterMaskIdLow = 0;
filter.FilterFIFOAssignment = CAN_RX_FIFO0;
filter.FilterBank = 0;
filter.FilterMode = CAN_FILTERMODE_IDMASK;
filter.FilterScale = CAN_FILTERSCALE_16BIT;
filter.FilterActivation = ENABLE;
filter.SlaveStartFilterBank = 0;
if (HAL_CAN_ConfigFilter(&can_handle, &filter) != HAL_OK)
return (1);
I want to send accelerometer values over BLE to an iOS app using a nordic nRF52. The app works perfectly with standard BLE services (HeartRate Measurement, Thermometer etc), but not when I try and define a custom BLE Accelerometer Service. Is there anything I need to do specifically when defining UUID's and things? Any help would be much appreciated, thanks.
Below is my custom Accelerometer class, and the main.cpp uploaded to the nRF52 below that.
#ifndef __BLE_ACCELEROMETER_SERVICE__
#define __BLE_ACCELEROMETER_SERVICE__
#include "ble/BLE.h"
#define UUID_ACCELEROMETER_SERVICE "00000000-0000-1000-7450-BE2E44B06B00"
#define UUID_X_CHARACTERISTIC "00000000-0000-1000-7450-BE2E44B06B01"
#define UUID_Y_CHARACTERISTIC "00000000-0000-1000-7450-BE2E44B06B02"
#define UUID_Z_CHARACTERISTIC "00000000-0000-1000-7450-BE2E44B06B03"
/**
* #class AccelerometerService
* #brief BLE Custom Accelerometer Service. This provides the x, y and z values of the SEEED 101020051 Grove accelerometer connected to the Nordic nRF52 DK.
*/
class AccelerometerService
{
public:
/**
* #brief Add the Accelerometer Service to an existing BLE object, initialize with values for x, y and z readings, represented as doubles.
* #param _ble Reference to the BLE device
* #param _x Initial value for the x axis
* #param _y Initial value for the y axis
* #param _z Initial value for the z axis
*/
AccelerometerService(BLE &_ble, double _x = 0, double _y = 0, double _z = 0) :
ble(_ble),
x(_x),
y(_y),
z(_z),
xAngleCharacteristic(UUID_X_CHARACTERISTIC, &x, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
yAngleCharacteristic(UUID_Y_CHARACTERISTIC, &y, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
zAngleCharacteristic(UUID_Z_CHARACTERISTIC, &z, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {
GattCharacteristic *readings[] = {&xAngleCharacteristic, &yAngleCharacteristic, &zAngleCharacteristic, };
GattService accelerometerService(UUID_ACCELEROMETER_SERVICE, readings, sizeof(readings) / sizeof(GattCharacteristic *));
ble.addService(accelerometerService);
}
/**
* #brief Update the x axis rotation with a new value.
* #param _x - New x value from accelerometer
*/
void update_x(uint8_t _x) {
x = _x;
ble.gattServer().write(xAngleCharacteristic.getValueHandle(), &x, 1);
}
/**
* #brief Update the y axis rotation with a new value.
* #param _z - New y value from accelerometer
*/
void update_y(uint8_t _y) {
y = _y;
ble.gattServer().write(yAngleCharacteristic.getValueHandle(), &y, 1);
}
/**
* #brief Update the z axis rotation with a new value.
* #param _z - New z value from accelerometer
*/
void update_z(uint8_t _z) {
z = _z;
ble.gattServer().write(zAngleCharacteristic.getValueHandle(), &z, 1);
}
protected:
/**
* A reference to the underlying BLE instance that this object is attached to.
* The services and characteristics will be registered in this BLE instance.
*/
BLE &ble;
/**
* The current x axis rotation, represented as a double
*/
uint8_t x;
/**
* The current y axis rotation, represented as a double
*/
uint8_t y;
/**
* The current z axis rotation, represented as a double
*/
uint8_t z;
/**
* A ReadOnlyGattCharacteristic that allows access to the peer device to the
* x axis rotation value through BLE.
*/
ReadOnlyGattCharacteristic<uint8_t> xAngleCharacteristic;
/**
* A ReadOnlyGattCharacteristic that allows access to the peer device to the
* y axis rotation value through BLE.
*/
ReadOnlyGattCharacteristic<uint8_t> yAngleCharacteristic;
/**
* A ReadOnlyGattCharacteristic that allows access to the peer device to the
* z axis rotation value through BLE.
*/
ReadOnlyGattCharacteristic<uint8_t> zAngleCharacteristic;
};
#endif /* __BLE_ACCELEROMETER_SERVICE__ */
Below is the main.cpp file I am using via mbed.org.
#include "mbed.h"
#include "ble/BLE.h"
#include "AccelerometerService.h"
DigitalOut led1(LED1);
DigitalOut led2(LED2);
static AccelerometerService *accelerometerServicePtr;
// Function declarations
void bleInitComplete(BLE::InitializationCompleteCallbackContext *);
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *);
// Set device name and inital setup options
static const char DEVICE_NAME[] = "nRF52";
static const uint16_t uuid16_list[] = {0xFFFF};
static volatile bool triggerSensorPolling = false;
static float x = 10.0; // Dummy values for accelerometer for now
static float y = 15.0;
static float z = 18.0;
/*
* Initialization callback
*/
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
BLE &ble = params->ble;
ble_error_t error = params->error;
if (error != BLE_ERROR_NONE){
printf("*** Error occured ***\n");
return;
}
/* Ensure that it is the default instance of BLE */
if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
return;
}
ble.gap().onDisconnection(disconnectionCallback);
// Setup primary service
accelerometerServicePtr = new AccelerometerService(ble, x, y, z);
// Setup advertising
ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
// Advertising payload has a maximum of 31 bytes
// BLE only, no classic BT
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED |
GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
// Add name
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
// UUIDs broadcast in advertising packet
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
// Set advertising interval
ble.gap().setAdvertisingInterval(100); //100ms
// Start advertising
ble.gap().startAdvertising();
}
/**
* Restart advertising on disconnection
*/
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *)
{
BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising();
}
/**
* This function is called when the ble initialization process has failed
*/
void onBleInitError(BLE &ble, ble_error_t error)
{
/* Avoid compiler warnings */
(void) ble;
(void) error;
/* Initialization error handling should go here */
}
int main()
{
// Initialize program
printf("\n\r *** Starting Main Loop *** \r\n");
BLE &ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
ble.init(bleInitComplete);
while (ble.hasInitialized() == false)
{
while (true)
{
if (triggerSensorPolling && ble.gap().getState().connected) {
triggerSensorPolling = false;
accelerometerServicePtr->update_x(x);
accelerometerServicePtr->update_y(y);
accelerometerServicePtr->update_z(z);
}
else {
ble.waitForEvent(); // Infinite loop waiting for BLE interrupt events
}
}
}
}
This is wrong, you are sending a bad advertising packet. (0xFFFF == Insert 16 bit service here)
...
uuid16_list[] = {0xFFFF};
...
...
COMPLETE_LIST_128BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)
There are for Bluetooth reserved 16 bit identifiers, which use the reserved UUID space.
Check This page: What range of Bluetooth UUIDs can be used for vendor defined profiles?
What you need to do is specify the full UUID in the 128 bit list.
I cant compile this but try something like this
char 128bitlist[] = {,0x00,0x00,0x00,0x00 ,0x00,0x00 ,0x10,0x00 ,0x74,0x50 ,0xBE,0x2E,0x44,0xB0,0x6B,0x00};
...
...
ble.gap().accumulateAdvertisingPayload (GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (uint8_t *) 128bitlist, 1);
An outstanding tool for checking your advertising data is Lightblue. It is free and really informative. You should check the advertising on both Android and IOS with this tool.
Another thing to check is that you dont overfill the advertising packet. If your device name is too long, plus the 128 bit UUID, you can overfill and corrupt the packet. Try removing the name or making it really short.
There are two things need to be consider.
First,
To communicate a BLE device which has a custom service and its characteristics then you need a matching Application at Central side i.e. at mobile side for example. Because the standard application will always look for intended standard profile only.
Second,
To implement custom profile into your device firmware, Nordic has provided an example for their UART (NUS) profile. You can use that example as a reference and do the changes wherever required for example the UUID for Service and Characteristics.
In this example I will use SPI2 run in mode Master(NSS pin control by software) to send data.
SPI3 run in mode Slave (NSS pin control by harware) receive data using DMA.
PC2 (SPI2 MISO) connect to PC11(SPI3 MISO).
PC3 (SPI2 MOSI) connect to PC12(SPI3 MOSI).
PB10 (SPI2 SCK) connect to PC10 (SPI3 SCK).
PC6 (SPI2 NSS pin control by sofware) connect to PA4(SPI3 NSS pin control by hardware).
main.c
#include "stm32f4xx_hal.h"
#define spi_enable HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET)
#define spi_disable HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET)
SPI_HandleTypeDef hspi2;
SPI_HandleTypeDef hspi3;
DMA_HandleTypeDef hdma_spi3_rx;
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_SPI2_Init(void);
static void MX_SPI3_Init(void);
uint8_t send_data=32,receive_data=0;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_SPI2_Init();
MX_SPI3_Init();
HAL_SPI_Receive_DMA(&hspi3,&receive_data,1);
while (1)
{
spi_enable;
HAL_SPI_Transmit_IT(&hspi2,&send_data,1);
HAL_Delay(1000);
send_data++;
}
}
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
if(hspi->Instance==hspi2.Instance)
{
spi_disable;
}
}
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
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 = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|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_DIV4;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/* SPI2 init function */
static void MX_SPI2_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
}
/* SPI3 init function */
static void MX_SPI3_Init(void)
{
hspi3.Instance = SPI3;
hspi3.Init.Mode = SPI_MODE_SLAVE;
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi3.Init.NSS = SPI_NSS_HARD_INPUT;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi3) != HAL_OK)
{
Error_Handler();
}
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
}
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);
/*Configure GPIO pin : PC6 */
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* #brief This function is executed in case of error occurrence.
* #param None
* #retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler */
/* User can add his own implementation to report the HAL error return state */
while(1)
{
}
/* USER CODE END Error_Handler */
}
#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,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif
/**
* #}
*/
/**
* #}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
During debugging, I found that SystemClock_config() function continuously running given below code.
/* Wait till HSE is ready */
while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)
{
if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
why is it not going to further function?
If you are using RTOS this could help:
http://www.keil.com/support/docs/3931.htm
Therefore the CMSIS RTOS already configures the priorities for some interrupts. Try to uncomment following code from SystemClock_Config() additionally to the description:
//HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
//HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
//HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
I hope it helps.
I know FILE is a typedef-ed struct, but where can I look up the actual definition of struct FILE using man page?
If you start at /usr/include/stdio.h, you would find this line:
typedef struct _IO_FILE FILE;
Just grepping for __IO_FILE in /usr/include reveals that the struct is defined in /usr/include/libio.h
My /usr/include/libio.h shows the following definition for __IO_FILE:
struct _IO_FILE {
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags
/* The following pointers correspond to the C++ streambuf protocol. */
/* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
char* _IO_read_ptr; /* Current read pointer */
char* _IO_read_end; /* End of get area. */
char* _IO_read_base; /* Start of putback+get area. */
char* _IO_write_base; /* Start of put area. */
char* _IO_write_ptr; /* Current put pointer. */
char* _IO_write_end; /* End of put area. */
char* _IO_buf_base; /* Start of reserve area. */
char* _IO_buf_end; /* End of reserve area. */
/* The following fields are used to support backing up and undo. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base; /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno;
#if 0
int _blksize;
#else
int _flags2;
#endif
_IO_off_t _old_offset; /* This used to be _offset but it's too small. */
#define __HAVE_COLUMN /* temporary */
/* 1+column number of pbase(); 0 is unknown. */
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];
/* char* _save_gptr; char* _save_egptr; */
_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};
struct _IO_FILE_complete
{
struct _IO_FILE _file;
#endif
#if defined _G_IO_IO_FILE_VERSION && _G_IO_IO_FILE_VERSION == 0x20001
_IO_off64_t _offset;
# if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
/* Wide character stream stuff. */
struct _IO_codecvt *_codecvt;
struct _IO_wide_data *_wide_data;
struct _IO_FILE *_freeres_list;
void *_freeres_buf;
size_t _freeres_size;
# else
void *__pad1;
void *__pad2;
void *__pad3;
void *__pad4;
size_t __pad5;
# endif
int _mode;
/* Make sure we don't get into trouble again. */
char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
#endif
};