+ *
+ * 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 "spi.h"
+#include "usb_device.h"
+#include "gpio.h"
+
+/* Private includes ----------------------------------------------------------*/
+/* USER CODE BEGIN Includes */
+#include "main_cpp.h"
+/* USER CODE END Includes */
+
+/* Private typedef -----------------------------------------------------------*/
+/* USER CODE BEGIN PTD */
+
+/* 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 ---------------------------------------------------------*/
+
+/* USER CODE BEGIN PV */
+
+/* USER CODE END PV */
+
+/* Private function prototypes -----------------------------------------------*/
+void SystemClock_Config(void);
+/* USER CODE BEGIN PFP */
+
+/* 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 */
+
+ /* Configure the system clock */
+ SystemClock_Config();
+
+ /* USER CODE BEGIN SysInit */
+
+ /* USER CODE END SysInit */
+
+ /* Initialize all configured peripherals */
+ MX_GPIO_Init();
+ MX_SPI1_Init();
+ MX_USB_DEVICE_Init();
+ /* USER CODE BEGIN 2 */
+
+ setup();
+
+ /* USER CODE END 2 */
+
+ /* Infinite loop */
+ /* USER CODE BEGIN WHILE */
+ while (1)
+ {
+ /* USER CODE END WHILE */
+
+ /* USER CODE BEGIN 3 */
+ loop();
+ }
+ /* USER CODE END 3 */
+}
+
+/**
+ * @brief System Clock Configuration
+ * @retval None
+ */
+void SystemClock_Config(void)
+{
+ RCC_OscInitTypeDef RCC_OscInitStruct = {0};
+ RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
+ RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
+
+ /** Initializes the RCC Oscillators according to the specified parameters
+ * in the RCC_OscInitTypeDef structure.
+ */
+ 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 buses 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();
+ }
+ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
+ PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
+ if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
+ {
+ Error_Handler();
+ }
+}
+
+/* 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 */
+ __disable_irq();
+ while (1)
+ {
+ }
+ /* 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,
+ ex: 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****/
diff --git a/examples_stm32/GettingStarted/Core/Src/main_cpp.cpp b/examples_stm32/GettingStarted/Core/Src/main_cpp.cpp
new file mode 100644
index 000000000..99db8d4c3
--- /dev/null
+++ b/examples_stm32/GettingStarted/Core/Src/main_cpp.cpp
@@ -0,0 +1,110 @@
+#include "main_cpp.h"
+#include
+
+// Includes he peripheral initialization files (make sure to mark
+// "Generate peripheral initialization as a pair of '.c/.h' files per
+// peripheral" in CubeMX editor -> Project Manager -> Code Generator
+#include "spi.h"
+#include "usbd_cdc_if.h"
+
+// RF24 driver
+// Copy the RF24 repository files into a new folder: Drivers/RF24
+#include "Drivers/RF24/RF24.h"
+
+// The BluePill has a USB Virtual COM, but you may customize this define
+// to what fits your hardware
+#define print(x) CDC_Transmit_FS((uint8_t*) x, sizeof(x))
+
+// Instantiate an object for the nRF24L01 transceiver and the respective spi
+RF24 radio(RF24_PB0, RF24_PB1); // using pin PB0 for the CE pin, and pin PB1 for the CSN pin
+RF24_SPI rf24_spi;
+
+// Let these addresses be used for the pair
+uint8_t address[][6] = { "1Node", "2Node" };
+// It is very helpful to think of an address as a path instead of as
+// an identifying device destination
+
+// Use this variable to control whether this node is sending or receiving
+bool role = false; // true = TX role, false = RX role
+
+// For this example, we'll be using a payload containing a single number
+// that will be incremented on every successful transmission
+int payload = 0;
+
+void setup() {
+ // Initialize the RF24 SPI driver
+ rf24_spi.begin(&hspi1);
+
+ // initialize the transceiver on the SPI bus
+ if (!radio.begin()) {
+ print("radio hardware is not responding!!\n");
+ while (1) {} // hold in infinite loop
+ }
+
+ // print example's introductory prompt
+ print("RF24/examples/GettingStarted\n");
+
+ // To set the radioNumber via the Serial monitor on startup
+ if (role)
+ print("This is a TX node\n");
+ else
+ print("This is a RX node\n");
+
+ // Set the PA Level low to try preventing power supply related problems
+ // because these examples are likely run with nodes in close proximity to
+ // each other.
+ radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
+
+ // save on transmission time by setting the radio to only transmit the
+ // number of bytes we need to transmit a float
+ radio.setPayloadSize(sizeof(payload)); // float datatype occupies 4 bytes
+
+ // set the TX address of the RX node into the TX pipe
+ radio.openWritingPipe(address[role]); // always uses pipe 0
+
+ // set the RX address of the TX node into a RX pipe
+ radio.openReadingPipe(1, address[!role]); // using pipe 1
+
+ // additional setup specific to the node's role
+ if (role)
+ radio.stopListening(); // put radio in TX mode
+ else
+ radio.startListening(); // put radio in RX mode
+}
+
+void loop() {
+ char string_buffer[80];
+
+ if (role)
+ {
+ // This device is a TX node
+
+ int start_timer = rf24_get_time_us(); // start the timer
+ bool report = radio.write(&payload, sizeof(float)); // transmit & save the report
+ int end_timer = rf24_get_time_us(); // end the timer
+
+ if (report) {
+ sprintf(string_buffer, "Transmission successful! Time to transmit = %d us. Sent: %d\n", end_timer - start_timer, payload);
+ print(string_buffer); // print payload sent
+ payload += 1; // increment float payload
+ } else {
+ print("Transmission failed or timed out\n"); // payload was not delivered
+ }
+
+ // to make this example readable in the serial monitor
+ delay(1000); // slow transmissions down by 1 second
+
+ }
+ else
+ {
+ // This device is a RX node
+
+ uint8_t pipe;
+ if (radio.available(&pipe)) { // is there a payload? get the pipe number that recieved it
+ uint8_t bytes = radio.getPayloadSize(); // get the size of the payload
+ radio.read(&payload, bytes); // fetch payload from FIFO
+ sprintf(string_buffer, "Received %d bytes on pipe %d: %d\n", bytes, pipe, payload);
+ }
+ } // role
+}
+
diff --git a/examples_stm32/GettingStarted/Core/Startup/startup_stm32f103c8tx.s b/examples_stm32/GettingStarted/Core/Startup/startup_stm32f103c8tx.s
new file mode 100644
index 000000000..f2b7fbe38
--- /dev/null
+++ b/examples_stm32/GettingStarted/Core/Startup/startup_stm32f103c8tx.s
@@ -0,0 +1,365 @@
+/**
+ *************** (C) COPYRIGHT 2017 STMicroelectronics ************************
+ * @file startup_stm32f103xb.s
+ * @author MCD Application Team
+ * @brief STM32F103xB Devices vector table for Atollic toolchain.
+ * This module performs:
+ * - Set the initial SP
+ * - Set the initial PC == Reset_Handler,
+ * - Set the vector table entries with the exceptions ISR address
+ * - Configure the clock system
+ * - Branches to main in the C library (which eventually
+ * calls main()).
+ * After Reset the Cortex-M3 processor is in Thread mode,
+ * priority is Privileged, and the Stack is set to Main.
+ ******************************************************************************
+ * @attention
+ *
+ *