Hallo, ich sitze nun schon etwas länger an einem Problem und komme nicht weiter. Mir gelingt es nicht den sprintf befehl auf meinem Cortex M0 zu verwenden. #include <stdio.h> ... ... while (1) { char buffer[10] = "hallo"; uint8_t i=1; //sprintf(buffer, "Test %u",i); sprintf(buffer, "Test") HAL_UART_Transmit(&huart1, (char*) buffer, 100, 100); HAL_Delay(1000); } Mit sprintf(buffer,"Test); funktioniert alles einwandfrei. Sobald ich allerdings die erweiterten Funktionen von sprintf verwenden möchte geht da garnichts mehr. Der µC lässt sich nichtmal mehr Debuggen. Meine Entwicklungsumgebung ist Eclipse mit einem Makefile-Projekt. ST-Linker zum flashen. Habe auch schon viele dinge getestet. CAN-BUS, UART usw.. das funktioniert alles. Nur das einfache sprintf macht mich verrückt. Auch snprintf habe ich versucht. Diese Ausgabe bekomme ich von meiem Debugger wenn ich versuche zu debuggen. Open On-Chip Debugger 0.8.0 (2014-04-28-08:39) Licensed under GNU GPL v2 For bug reports, read http://openocd.sourceforge.net/doc/doxygen/bugs.html srst_only separate srst_nogate srst_open_drain connect_deassert_srst Started by GNU ARM Eclipse Info : This adapter doesn't support configurable speed Info : STLINK v2 JTAG v17 API v2 SWIM v0 VID 0x0483 PID 0x3748 Info : using stlink api v2 Info : Target voltage: 2.925402 Info : stm32f0x.cpu: hardware has 4 breakpoints, 2 watchpoints Info : accepting 'gdb' connection from 3333 Info : device id = 0x20016448 Info : flash size = 128kbytes undefined debug reason 7 - target needs reset target state: halted target halted due to debug-request, current mode: Thread xPSR: 0xc1000000 pc: 0x08001c90 msp: 0x20003ffc semihosting is enabled target state: halted target halted due to debug-request, current mode: Thread xPSR: 0xc1000000 pc: 0x08001c90 msp: 0x20003ffc, semihosting Info : odd number of bytes to write, padding with 0xff target state: halted target halted due to breakpoint, current mode: Thread xPSR: 0x61000000 pc: 0x2000003a msp: 0x20003ffc, semihosting target state: halted target halted due to debug-request, current mode: Thread xPSR: 0xc1000000 pc: 0x08001c90 msp: 0x20003ffc, semihosting target state: halted target halted due to debug-request, current mode: Thread xPSR: 0xc1000000 pc: 0x08001c90 msp: 0x20003ffc, semihosting ===== arm v7m registers (0) r0 (/32): 0xFFFFFFFF (1) r1 (/32): 0xFFFFFFFF (2) r2 (/32): 0xFFFFFFFF (3) r3 (/32): 0xFFFFFFFF (4) r4 (/32): 0xFFFFFFFF (5) r5 (/32): 0xFFFFFFFF (6) r6 (/32): 0xFFFFFFFF (7) r7 (/32): 0xFFFFFFFF (8) r8 (/32): 0xFFFFFFFF (9) r9 (/32): 0xFFFFFFFF (10) r10 (/32): 0xFFFFFFFF (11) r11 (/32): 0xFFFFFFFF (12) r12 (/32): 0xFFFFFFFF (13) sp (/32): 0x20003FFC (14) lr (/32): 0xFFFFFFFF (15) pc (/32): 0x08001C90 (16) xPSR (/32): 0xC1000000 (17) msp (/32): 0x20003FFC (18) psp (/32): 0xFFFFFFFC (19) primask (/1): 0x00 (20) basepri (/8): 0x00 (21) faultmask (/1): 0x00 (22) control (/2): 0x00 ===== Cortex-M DWT registers (23) dwt_ctrl (/32) (24) dwt_cyccnt (/32) (25) dwt_0_comp (/32) (26) dwt_0_mask (/4) (27) dwt_0_function (/32) (28) dwt_1_comp (/32) (29) dwt_1_mask (/4) (30) dwt_1_function (/32) Danke schonmal für eure Hilfe.
Manollo139 schrieb: > char buffer[10] = "hallo"; Mach das Array mal größer. 9 druckbare Zeichen sind nicht sehr viel. Durch "Test " gehen dir da schon mal 5 verloren und wenn dein sprintf für die Ausgabe der Zahl dann auch noch eine paar Zeichen verbrutzelt (Feldbreite etc.) dann bist du da schnell drüber.
Hast du genug Heap reserviert? Üblicherweise verwenden *printf-Funktionen diesen zur Formatierung. Wenn du unter Windows arbeitest könntest du überlegen den ARM Compiler zu verwenden: http://www2.keil.com/stmicroelectronics-stm32/mdk Der macht das sicher so. Der Heap wird im dort meist im startup_*.s konfiguriert.
Das liegt daran, dass der gcc hier so intelligent ist, dass für
1 | sprintf(buffer, "Test"); |
kein sprintf nötig ist, sondern ein strcpy reicht. Und wenn du sonst nirgends sprintf und co verwendest, wird es auch nicht dazu gelinkt. Da für strcpy kein Heap benötigt wird kommt es auch nicht zum Fehler. Als Alternative empfehle ich hier eine abgespeckte Version von (sn)printf die ohne dynamischen Speicher auskommt. Dazu dürfte Google reichlich Treffer liefern.
Hier mal mein kompletter Quellcode für das Testprojekt in dem ich den sprintf ans laufen bekommen möchte. Mit printf werde ich das ganze jetzt erstmal versuchen. Wäre aber über weitere tipps schonmal dankbar :-) /** ************************************************************************ ****** * File Name : main.c * Date : 26/05/2015 12:44:11 * Description : Main program body ************************************************************************ ****** * * COPYRIGHT(c) 2015 STMicroelectronics * * 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 "stm32f0xx_hal.h" #include <stdio.h> /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private variables ---------------------------------------------------------*/ UART_HandleTypeDef huart1; /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART1_UART_Init(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ 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(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ char buffer[100] = ""; uint8_t i = 1; sprintf(buffer, "Test %u",i); //sprintf(buffer, "Value of Pi "); //HAL_UART_Transmit(&huart1, (char*) buffer, 100, 100); //HAL_Delay(1000); } /* USER CODE END 3 */ } /** System Clock Configuration */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInit; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = 16; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6; RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1; HAL_RCC_OscConfig(&RCC_OscInitStruct); RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1); PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1; PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1; HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); __SYSCFG_CLK_ENABLE(); } /* USART1 init function */ void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 9600; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; huart1.Init.OneBitSampling = UART_ONEBIT_SAMPLING_DISABLED; huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; HAL_UART_Init(&huart1); } /** Configure pins as * Analog * Input * Output * EVENT_OUT * EXTI PA2 ------> TSC_G1_IO3 PA3 ------> TSC_G1_IO4 PA6 ------> TSC_G2_IO3 PA7 ------> TSC_G2_IO4 PB0 ------> TSC_G3_IO2 PB1 ------> TSC_G3_IO3 PB10 ------> I2C2_SCL PB11 ------> I2C2_SDA PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO PB15 ------> SPI2_MOSI */ void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; /* GPIO Ports Clock Enable */ __GPIOC_CLK_ENABLE(); __GPIOA_CLK_ENABLE(); __GPIOB_CLK_ENABLE(); /*Configure GPIO pins : PC0 PC5 PC6 PC7 PC8 PC9 */ GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pins : PC1 PC2 */ GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pin : PA0 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pins : PA2 PA3 PA6 PA7 */ GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; GPIO_InitStruct.Alternate = GPIO_AF3_TSC; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pins : PB0 PB1 */ GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; GPIO_InitStruct.Alternate = GPIO_AF3_TSC; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pins : PB10 PB11 */ GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; GPIO_InitStruct.Alternate = GPIO_AF1_I2C2; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pins : PB13 PB14 PB15 */ GPIO_InitStruct.Pin = GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; GPIO_InitStruct.Alternate = GPIO_AF0_SPI2; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ #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****/
Bezüglich der Aussage zur Buffergröße. Ich hatte testweise auch mal 32,100,200 usw getestet. Brachte keine Besserung.
Am Ende wird von der newlib immer die Funktion
1 | char *sbrk(int increment); |
gerufen. Die muss passend implementiert sein. Wie das bei dir aussieht kann nur der startup-Code und das Linkerscript beantworten. Dabei wirst du dich aber auf den Hintern setzten, wenn du siehst wieviel Speicher da angefordert wird für dein simples Beispiel. Und vergiss eins nie: Solange die sbrk-Funktion nicht thread- bzw. interruptsaved programmiert ist, kannst du diese Funktionen (egal ob printf oder sprintf oder all die so ähnlich heissen) nicht ohne besondere Vorkehrungen in Interrupts verwenden. Deshalb gebe ich dir nochmal dringend den Rat eine kleine Alternative zu verwenden, die ohne dynamischen Speicher auskommt.
Wenn du wenig Flash hast (was beim F072 schnell der Fall ist) schau dir mal die sehr kompkte Lib von fleissigen Chan an: http://elm-chan.org/fsw/strf/xprintf.html Cheers
Manollo139 schrieb: > char buffer[100] = ""; > uint8_t i = 1; > sprintf(buffer, "Test %u",i); > //sprintf(buffer, "Value of Pi "); > > //HAL_UART_Transmit(&huart1, (char*) buffer, 100, 100); > //HAL_Delay(1000); Huch? War's das etwa? Und dafür braucht man ein sprintf() ? Wenn ich solchen Quellcode sehe, krieg ich regelmäßig ganz schlechte Laune. Also: für 99.99975 Prozent aller Textausgaben aus einem µC auf irgend einen verdammten Kanal - ob nun UART oder CDC oder sonstwas - braucht man alles mögliche andere, zum Beispiel eine gepufferte Ausgabe, die im Hintergrund ihren Job verrichtet, ohne daß man sowas wie "HAL_UART_Transmit" oder gar "HAL_Delay" bräuchte - ABER KEIN SPRINTF und Konsorten. Zum Kuckuck nochmal. W.S.
W.S. schrieb: > Also: für 99.99975 Prozent aller Textausgaben aus einem µC auf irgend > einen verdammten Kanal Die genaue Zahl ist 99.99976 ... Hier ging es darum warum sprintf nicht geht und nicht warum man es einsetzt. Du hast zwar Recht, dass es nicht immer nötig ist, aber deswegen musst du am frühen Morgen keine schlechte Laune kriegen. Hab ich mir auch abgewöhnt, obwohl ich schon Kotzen könnte wenn ich sehe, was aus trivialen Sachen für Code entsteht wenn man die Libs von ST benutzt.
Habe das Problem lösen können! Habe mein Makefile um folgende Zeile ergänzt. LDFLAGS += -u _printf_float Gruß
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.