the code to flip the led is fairly genericAt the level of the code you showed, it better be! The question is "how ridiculous" is the chip_init() part, and the library functions (if any) under your PIN_xxx macros? (those are your macros (that you've mentioned in other threads), rather than STLib or CMSIS functions, right?) At 1.1k, your binary is very nearly exactly the same size as the Arduino BLINK example (for ATmega328) that does the same thing. And a lot of people criticize the arduino libraries for being bloated.
Development environment:
tried successfully on CoIDE and Keil.
CoIDE: I used an earlier version that has no direct support for the ST chip. So I compiled it to a generic CM0 chip. With the st standard peripheral libraries, the code size is 1.1k - 1.7k, depending on compiler settings;
Keil: with microlib and cross-modulation optimization turned on, I got 1.0k - 1.6k. However, gcc is much faster in compilation time.
Keil: with microlib and cross-modulation optimization turned on, I got 1.0k - 1.6k. However, gcc is much faster in compilation time.Even 1k seems like a lot to blink an LED. Of course, maybe 1k is the smallest size that the tool will report.
Keil: with microlib and cross-modulation optimization turned on, I got 1.0k - 1.6k. However, gcc is much faster in compilation time.Even 1k seems like a lot to blink an LED. Of course, maybe 1k is the smallest size that the tool will report.
Regulated External Supply
In this mode, the PSoC 4200 is powered by an external power
supply that must be within the range of 1.71 to 1.89 V (1.8 ±5%);
note that this range needs to include power supply ripple too. In
this mode, VCCD, VDDA, and VDDD pins are all shorted
together and bypassed. The internal regulator is disabled in
firmware.
The programmer... are everywhere on the bay for $5 dollars.
I'm loving this.
it is a shame that more people aren't trying out those chips.
The STM8 chips are incredibly inexpensive - I have a few of them on a boat from China at 30 cents apiece (STM8S003F). Very difficult to beat at those price points.How about a Cortex M0 with 8k flash and 2k SRAM (http://www.cypress.com/?mpn=CY8C4013SXI-400) for the same price?
Biggest problem with the STM8 is the compiler. Cosmic has a 1 yr 32kB free license (sponsored by ST while it lasts) or a 8kB for indefinitly.
Some other compiler farmers also have those small free compiler try outs but nothing substantial.
The STM8 tends to be overlooked because of the very low price of ARM Cortex parts, but it's a surprisingly fast micro for an 8 bitter.In present time anno 2014 I agree, probably would also choose the Arm now, but the STM8 is out since 2008 when there were no equally cheap Arm micros.
Biggest problem with the STM8 is the compiler.
Probably the ARM M0 will take over the 8 bit domain,
This is preposterous! The raw power of the 32b ARM cannot be harnessed with a mere soldering iron, a TSSOP adapter board, and a few wires!
An actual thing you'll use more than once (like a flight controller) is a whole other ball of wax though.
if youre a rank beginner its a good idea to pick up one of these [bona fide originals]. but if experienced or like me have lots of frames and motors kicking around its nice to be able to crank out a half dozen of the cheap tricks for the same price.
Here's what I don't get, personally: You can hack that nasty mess together, or you can spend like $8 to have OSH Park mail you a PCB of the same size, with your custom layout on it. Certainly the difference between a $1 dev board and an $8 dev board is not make-or-break territory, is it? A circuit that does anything interesting is going to double the cost anyway, at the very least.
I realize some people like to save every last cent / quid / gil, and others just want to do something with the parts they have in a junk drawer. That's fair. Different strokes and all that. There's something to be said for being industrious enough to get a working circuit out of a scrap heap. An actual thing you'll use more than once (like a flight controller) is a whole other ball of wax though. I'm getting to where I debate whether to bother with a breadboard or just order a prototype PCB now. (That might be because I often don't recover the breadboard from its original test circuit though.)
SirNick, i don't think you get the point.
SirNick, i don't think you get the point.
That seems to be the case. ;)
Should sell these on tindie
There are quite a few of such "undocumented" features,............, or flash size (103 vs. 207).Maybe I misunderstand but ST provides the exact flash and RAM size for each specific device?
ST provides the exact flash and RAM size for each specific device?
Not trying to be the asshole here, was maybe a bit harsher then i intended ;). But you know what i'm saying..
Other beginners would be a lot better off spending $20-30 and getting a plug&play board like a Launchpad.
Nice breakouts btw. ... Should sell these on tindie ;)
It has surprised me that no one has attempted to do that: get a pcb that has minimal parts, like decoupling caps, or space for a crystal, a swd header, and put it in dip format.
with the STM8 this is not possible to my knowledge
It has surprised me that no one has attempted to do that: get a pcb that has minimal parts, like decoupling caps, or space for a crystal, a swd header, and put it in dip format.
Looks like someone beat me to it: there are quite a few such boards on ebay - stm8s003f, voltage regulator, reset switch, isp header, a couple leds and 0.1" dip pin out, plus unfitted crystal.
All for less than $2 shipped. and seems to be fairly popular.
Now, all you need is some kind of arduino-like library and you are off to a great start.
$3 for two, not bad.
No western company can do this
Software side of the things will be the biggest challenge early on in the process.
int main(void)
{
while(1)
{
}
}
Program Size:
text data bss dec hex filename
1684 20 4 1708 6ac f0 getto.elf
BUILD SUCCESSFUL
Total time: 6 seconds
void chip_init(void) {
//SystemCoreClockHSI_2MHz(); //set clock to hsi, _2MHz, _4MHz, _8MHz, _16MHz
//CLK->PCKENR1=CLK->PCKENR2=0x00; //optional - disable all peripheral clocks
}
11) debugging:
Now, your stlink should have downloaded the code to your chip and the execution is halted on the first line of your main() - highlighted in green by EWSTM.
Your then can explore all the nice features of the IDE + debugger + chip.
Hope it helps.
It was pointed out to me, rightfully so, that the use of a commercial IDE (EWSTM) isn't exactly "ghetto".Baaah, the IAR STM8 version is free of charge till 8kB so what is cheaper then free exactly ? ;)
STVD
the free Cosmic STM8 compiler (also 8kB limit).
ST is very much like Microchip: great hardware, shitty software. STVD is so 1990s in terms of its interfaceYeah you might be right there, I am using it when I started with the ST7's that was begin 2000's, it was great then, even the simulator worked (never worked for the STM8 but the real time debug (SWIM) interface made that not such a pain anyway).
The STM8 chips are incredibly inexpensive - I have a few of them on a boat from China at 30 cents apiece (STM8S003F).
On the flip side, you may be able to get cosmic (or sdcc) to work with other IDEs (Eclipse or CB, for example). I never tried it myself but shouldn't be that difficult.To build should be possible but to debug requires a dedicated plugin interfacing the resonance rlink or stlink, never heard those existed for eclipse?
never heard those existed for eclipse?
Looks like someone beat me to it: there are quite a few such boards on ebay - stm8s003f, voltage regulator, reset switch, isp header, a couple leds and 0.1" dip pin out, plus unfitted crystal.Oooh, nice find. Thanks for the tip. :-+
All for less than $2 shipped. and seems to be fairly popular.
0.9ma @ 2Mhz,
3.9ma @ 16Mhz.
Highly unscientific testing of Keil mdk vs. gcc:
I have a simple blinky - similar to the one posted above but in modular form, in a project with the st standard peripheral library + my middleware (meaning that most of the code is unused).
1) Keil mdk:
with no optimization, and no discard of unused code, the output is 13KB.
with the most aggressive optimization (plus microlib) and discard unused code, the output is 1.6KB;
2) gcc-arm:
with no optimization, the output is over 37KB -> wouldn't fit my chip (STM32F030F);
with the most aggressive optimization and discard unused code, the output is 2.1KB.
amend:
3) IAR:
with no optimization, the output is 3KB - I think it must have cut unused code;
with the most aggressive optimization and multi-file compilation, the output is 1KB.
Debug config:
Program Memory Usage : 2316 bytes 14.1 % Full
Data Memory Usage : 584 bytes 28.5 % Full
Release config:
Program Memory Usage : 2204 bytes 13.5 % Full
Data Memory Usage : 584 bytes 28.5 % Full
#include <asf.h>
void configure_port_pins(void) {
struct port_config config_port_pin;
port_get_config_defaults(&config_port_pin);
config_port_pin.direction = PORT_PIN_DIR_OUTPUT;
port_pin_set_config(PIN_PA00, &config_port_pin);
}
int main (void) {
system_init();
delay_init();
configure_port_pins();
while(1) {
port_pin_toggle_output_level(PIN_PA00);
delay_ms(100);
}
}
such high memory usage, especially data, for such basic stuff.
not used to seeing such high memory usageA lot of those vendor libraries look like they were developed when the smallest chip had 64k+ of flash, so coming up with space-optimized init libraries wasn't at all important. If you really want to use those sub-$1 8-bit replacing ARMs with 16k or less, you may end up doing something else.
Quotesuch high memory usage, especially data, for such basic stuff.
Not too bad. Most of that stuff is the start-up code, clock mgmt, and interrupt table.
600 bytes are little bit too high - I typically get 100 - 200 bytes. But it could have included the zero-initiated data - depending on the compiler used / setting.
Quotenot used to seeing such high memory usageA lot of those vendor libraries look like they were developed when the smallest chip had 64k+ of flash, so coming up with space-optimized init libraries wasn't at all important. If you really want to use those sub-$1 8-bit replacing ARMs with 16k or less, you may end up doing something else.
For additional comparison, Arduino Due runs about 10k, Teensy 3 about 12k, and Energia (for TI CM4) to about 2.5k (!) A pruned bare-metal Keil/microlib is down to about 300 bytes, some of which is unused code that I can't figure out how to get rid of :-( (That includes the CM4 internally-sourced interrupt vectors and dummy ISRs (up through systick), but not the ones for "external" interrupts.)
It also suggests that 4KB of flash is probably the bare minimumMeh. Only if you assume that there won't be improved libraries and compiler options.
; BLINK in ARM Assembler
; For TI Stellaris/Tiva Launchpad, with LED on PF1..3
; Aug 2014, by Bill Westfield - released to Public Domain.
;
Stack_Size EQU 0x00000200
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
PRESERVE8
THUMB
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
; The program itself.
AREA |.text|, CODE, READONLY
newmain PROC
Reset_Handler
export Reset_Handler
ldr r0, =0x400FE108 ; Sysctl_rcgc2_r
ldr r1, [r0] ;; old val
orr r1, r1, #0x20 ;; enable PORTF clk
str r1, [r0]
nop ; Wait for PORTF to get clocked.
initf mov r1, #0xE ;; output bits
ldr r0, =0x40025000 ;; GPIO_PORTF
str r1, [r0, #0x400] ; set bit DIR to output
str r1, [r0, #0x51c] ; DEN enable digital IO
mov r2, #8 ; Bit 3: Green LED on Launchpad
loop ldr r1, [r0, #0x3FC] ; read DATA reg
eor r1, r2 ; complement bit
str r1, [r0, #0x3FC] ; write
mov r1, #(4*1024*1024) ;; Delay count
delay subs r1, r1, #1 ; decrement
bne delay
b loop
ENDP
END
The ST lib is exceptionally bad in code size and thus also speed.
STM32Cube
#include "stm32f0xx.h"
#include <stdio.h>
#include "main.h"
void init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
// LED: Configure PA0 and PA1 in output pushpull mode
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
int main (void) {
init();
GPIOA->BRR = GPIO_Pin_0; // Set PA0 to GND (LED on)
while (1) {
GPIOA->BSRR = GPIO_Pin_1; // Set PA1 HIGH (LED on)
Delay(500000L);
GPIOA->BRR = GPIO_Pin_1; // Set PA1 to GND (LED off)
Delay(500000L);
}
}
void Delay(__IO uint32_t nCount) {
while(nCount--) {
}
}
I built three small PCBs now which work great!
my code looks a little bit different to yours:
Did you use something "unusual"?
2) stlink (a stlink v2 clone): the connection there is SWDIO, SWDCLK (pin 19/20 from memory), Vcc/GND, plus BOOT0 to GND. Again, all user code, no bootloader.
I will use a 10k resistor soldered to GND.
I will try a weaker pulldown for BOOT0, say 100kOhm or more.
Success!
Unfortunately,...
Not knowing what "texane" is, I cannot be of much more for you.
Opensource stlink software: https://github.com/texane/stlink
// ---- Setup PLL for 48 MHz :) ----
RCC_DeInit();
RCC_HSEConfig(RCC_HSE_OFF);
RCC_PLLCmd(DISABLE);
RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_12);
// Flash: 1 WaitState for 24MHz < SysCLK < 48 MHz
FLASH_SetLatency(FLASH_Latency_1);
FLASH_PrefetchBufferCmd(ENABLE);
// Set ADC clock to internal 14MHz HSI source
RCC_HSI14Cmd(ENABLE);
RCC_HSI14ADCRequestCmd(ENABLE);
// and turn the PLL back on again
RCC_PLLCmd(ENABLE);
// set PLL as system clock source
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
// ---- End of Setup PLL for 48 MHz :) ----
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
// ADC-init for Temperature probe
ADC_DeInit(ADC1);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // on demand
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_TRGO;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 12 bit right aligned
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_ChannelConfig(ADC1, ADC_Channel_4, ADC_SampleTime_13_5Cycles);
ADC_DiscModeCmd(ADC1, ENABLE);
// ADC calibration; but not used as returned value ends nowhere now...
ADC_GetCalibrationFactor(ADC1);
ADC_Cmd(ADC1, ENABLE);
// Probe on PA3+4
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// end of init code ...
int readADC(void) {
uint32_t temp = 0;
GPIOA->BSRR |= (GPIO_Pin_3); // Enable Sensor
// throw awaynfirstresult like on AVR? first value is wrong.
ADC_StartOfConversion(ADC1);
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
for (uint8_t i = 0; i<16; i++) { // oversampling
ADC_StartOfConversion(ADC1);
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
temp += ADC_GetConversionValue(ADC1);
}
GPIOA->BRR |= (GPIO_Pin_3); // Disable Sensor, save power
return (temp>>4);
}
set WORKAREASIZE 0x1000
= (4K ram) In the board definition file you are using.set WORKAREASIZE 0x2000
,Nice board, I like the idea with the LDO. :D The space on the TSSOP20-adapter is too limited for that.
I wonder why you needed to adopt the linker files. I use the generic stm32f0xx-ones which come with the Eclipse plug-ins / standard peripheral lib, they work flawless.
/*
Linker subscript for STM32F051 definitions with 64K Flash and 8K RAM
Copyright RAISONANCE 2007
!!! This file is automatically generated by RIDE !!!
Do not modify it, as it will be erased at every link.
You can use, copy and distribute this file freely, but without any warranty.
*/
/* Memory Spaces Definitions */
ENTRY(Reset_Handler)
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 16K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K
}
/* highest address of the user mode stack */
_estack = 0x20001000;
How about pushing the frequency from 8 to 48 MHz
PF0 and PF1 should be usable as GPIO.
Always use a multimeter and check your soldering/connections
STM32F030-Test begins.
HCLK is 64 MHz, PCLK 64 MHz, System 64 MHz, ADC 14 MHz.
Temp: ~20 degrees C.
Temp: ~23 degrees C.
Temp: ~23 degrees C.
#define ADCx ADC1 //adc1 module used
typically a usart module.
[be modular]One of the annoying things about most of these 32bit chips is that a peripheral will be dependent on other registers of other peripherals that you can not easily derive, algorithmically (RCC[ADC1] |= ClkEnaBit[ADC1];) nor symbolically (RCC_ADC1 |= ADC1_CLOCKBIT;) The clock distribution registers are the most obvious example, but also things like:
#define ADCx ADC1 //adc1 module used
It is expecting that when you create your adc2 module, you can simply redefine ADCx to ADC2, and other changes, and the new adc2.c will recompile flawlessly.
if (GPIOx == GPIOA ) RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE);
else if (GPIOx == GPIOB) RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE);
else if (GPIOx == GPIOC) RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, ENABLE);
else if (GPIOx == GPIOD) RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOD, ENABLE);
are really ugly. And code-bloating. (And the ST peripheral library contains similar code, so it's not dannyf's fault.) It wouldn't be so bad if these were set up as inline, or templates, so that the compiler would eliminate unneeded code, but that's certainly NOT the case when the code is off in the external peripheral library.)static char text[255];
// init stuff
USART_InitTypeDef USART_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// UART1: Configure PA2 and PA3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1);
USART_InitStruct.USART_BaudRate = 57600;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART1, &USART_InitStruct);
USART_Cmd(USART1, ENABLE);
// end of init
void uart_tx(char *out) {
while (*out) {
while(!(USART1->ISR & USART_FLAG_TXE)) {
// Nothing, really.;
}
USART1->TDR = *out++;
}
}
RCC_ClocksTypeDef Clocks;
RCC_GetClocksFreq(&Clocks);
sprintf(text, "STM32F030-Test begins.\r\nHCLK is %d MHz, PCLK %d MHz, System %d MHz, ADC %d MHz.\n", (Clocks.HCLK_Frequency/1000000), (Clocks.PCLK_Frequency/1000000), (Clocks.SYSCLK_Frequency/1000000), (Clocks.ADCCLK_Frequency/1000000));
uart_tx(text);
MacBook-Air:Release koepi$ ./flash.sh
stm32flash 0.3
http://stm32flash.googlecode.com/
Using Parser : Intel HEX
Serial Config: 57600 8E1
Version : 0x31
Option 1 : 0x00
Option 2 : 0x00
Device ID : 0x0444 (STM32F030/F031)
- RAM : 8KiB (4096b reserved by bootloader)
- Flash : 64KiB (sector size: 4x1024)
- Option RAM : 12b
- System RAM : 3KiB
Wrote and verified address 0x080014f0 (100.00%) Done.
On a sidenote, I "assembled" a useful tableNice. Why can't datasheets contain such concise info.
QuoteOn a sidenote, I "assembled" a useful tableNice. Why can't datasheets contain such concise info.
stm32f103c8 boards are shown as having 128kByte flash
The values for RAM, flash location and size etc are deducted from the chip ID and not reported explicitly by the device. They are also not always true.
Well, they do:
<kinetis datasheet screenshot>
I wonder why your ghetto style works without problems without any additional part.
Well, maybe it's just the blinking of the LED at the default 8 MHz, that doesn't put much stress on the power lines.
it's not reliable in all conditions
where to finde the equivalent of ST Standard Peripheral Lib?
As the small stm8s don't have a bootloader, where is the program to upload the binary via SWIM?
combined with my own hands
Thus cheap 32bit power, combined with my own hands, is what makes me really happy :)
Ok, I put a ATtiny13 SOIC8 on a DIP adapter, used a socket and some RGB LED, tactile switches and stuff for testing that out, but the way too little memory was limiting everything.py :)
On a sidenote, I "assembled" a useful table [of Alternate Function Register values]Huh. That's interesting. I went to put together a similar table for the f103, and discovered that it apparently has a MUCH different way of configuring the "alternate functions"!
if (rand1_adc()) {PIN_FLP(LED_PORT, LED_A | LED_C);} //flip led
prices are really low for the 103sDoes anyone have the historical background for this chip/board? Usually, when some board appears on eBay from all the Chinese entrepreneurs who also sell clothing and cosmetics, it's a copy of something. (something profitable.) For example, there are plenty of "arduino pro micro" clones, and the DIP version of this ARM board looks like a clone of the Leaflabs "Maple mini." Sometimes they're involved in some quasi-legal hack (rooting your video game or cable box, for example.) But I don't recall seeing this "big JTAG connector + breakout" STM32F103 board before ...
the prices are really low for the 103s
But then you want to step up to lets say a 207 or 217 to do some IP stack and have some more ram.
You get a shock the cheapest listings on the same china ebay stores are now more expensive then farnell. Strange is it not?
Concerning cheapo ebay stm32 chips/boards, just an observation, the prices are really low for the 103s with and without boards, almost impossible to beat, the chip alone from farnell is more expensive.
But then you want to step up to lets say a 207 or 217 to do some IP stack and have some more ram.
You get a shock the cheapest listings on the same china ebay stores are now more expensive then farnell. Strange is it not?
For those of us who are too cheap to spare $5 (I am one of them), there is an approach that requires zero / no (incremental) cost to program those STM32 chips: your discovery boards. They have a debugger on board and can be made as programmer for those chips.
Surprisingly, it doesn't seem to be the case, at least for the STM32F207VCT6. It costs 7,84€ at Farnell, while Mouser sells them for 8,83€. The two Chinese sellers I found at Ebay sell them considerably cheaperWell then you have a different ebay search results than I do, I came up with only one supplier for around $11 incl shipping :palm:
for around $11 incl shipping
usart1_init(MYBAUD_RATE); //initialize the module
while (1) {
while (usart1_busy()) continue; //wait for the prior transmission to end
usart1_puts(my_string); //load up the string to be transmitted
//while (usart1_busy()) continue; //wait for the current transmission to end.
//in the ISR:
if (*_UxTX_ptr) { //0 indicates the end of the string - send null at the end
//if (*(_UxTX_ptr+1)) { //0 indicates the end of the string - don't send null at the end
F103C8s definitely have more than 64KB of flash -> they are actually CBs?
I wonder how the ghetto version looks on the scope.
I'm getting closer to understand this thing a bit better:
//pin frequency in Khz, Cpu frequency in Mhz.
PLLx F_CPU O0 O1
2 16 1595 3982
3 24 2393 5973
4 32 3191 7984
8 64 6383 15928
9 72 7181 17919
10 80 7979 19921
11 88 8777 21901
12 96 9575 23856
I am still a bit stuck on it since I need the 32kB free Cosmic compiler for my projects, 8k does not cut it.
PLLx F_CPU WS O0 O1
2 16 0 1595 3982
3 24 0 2393 5973
4 32 0 3191 7984
8 64 0 6383 15928
9 72 0 7181 17919
10 80 0 7979 19921
11 88 0 8777 21901
12 96 0 9575 23856
PLLx F_CPU WS O0 O1
2 16 1 1587 3935
3 24 1 2380 5903
4 32 1 3174 7871
8 64 1 6348 15742
9 72 1 7142 17710
10 80 1 7936 19678
11 88 1 8729 21645
12 96 1 9523 23613
PLLx F_CPU WS O0 O1
2 16 0 571 888
3 24 0 857 1333
4 32 0 1142 1777
6 48 0 1714 2666
8 64 0
10 80 0
11 88 0
12 96 0
PLLx F_CPU WS O0 O1
2 16 2 571 888
3 24 2 857 1333
4 32 2 1142 1777
6 48 2 1714 2666
8 64 2
10 80 2
11 88 2
12 96 2
The flash latency only comes into play when there is code read from the flash. Next to a latency flag there is a flag for a cacheing mechanism. The code for flipping a pin obviously fits very nicely into this cache. I find modern techniques mentioned for the ST-µCs like branch cache, instruction prefetch and so on.That is for the F2 series they have a branch cache, the F1 series only has a prefetch queue.
http://www.st.com/web/en/press/en/t2477 (http://www.st.com/web/en/press/en/t2477)
Thus more complex and unpredictable code flow will show the worst case performance,
stm32f7
The purpose of the Tightly-Coupled Memory (TCM) is to provide low-latency memory that the processor can use without the unpredictability that is a feature of caches.
But I fear that's nothing for ghetto style.
STM8S003F, doing pwm on tim1, ch3 (PC3).
to my knowledge there is no such project public available. You'd need to port a project yourself
Coding is super easy.
these libraries bloat the resulting binary way too much.
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
int main(void)
{
rcc_clock_setup_hsi(&hsi_8mhz[CLOCK_44MHZ]);
rcc_periph_clock_enable(RCC_GPIOE);
gpio_mode_setup(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO12);
while(1)
{
gpio_toggle(GPIOE, GPIO12);
for (i = 0; i < 2000000; i++)
__asm__("nop");
}
}
MacBook-Air:Release koepi$ ./flash.sh
stm32flash 0.3
http://stm32flash.googlecode.com/
Using Parser : Intel HEX
Serial Config: 57600 8E1
Version : 0x31
Option 1 : 0x00
Option 2 : 0x00
Device ID : 0x0444 (STM32F030/F031)
- RAM : 8KiB (4096b reserved by bootloader)
- Flash : 64KiB (sector size: 4x1024)
- Option RAM : 12b
- System RAM : 3KiB
Wrote and verified address 0x08001570 (100.00%) Done.
Charging with 610 mA. (Vprog 586mV, 36%.)
Charging with 612 mA. (Vprog 587mV, 36%.)
Charging with 610 mA. (Vprog 586mV, 36%.)
Charging with 609 mA. (Vprog 585mV, 36%.)
Charging with 608 mA. (Vprog 584mV, 36%.)
Charging with 609 mA. (Vprog 585mV, 36%.)
#include "stm32f0xx.h"
#include <stdbool.h>
#include <stdio.h>
#include "main.h"
static char text[255];
volatile uint32_t VREFINT_CAL = 0;
RCC_ClocksTypeDef Clocks;
volatile uint8_t charge_rate=0;
static const int resistance[3] = { 1150, 2300, 4400 };
static const bool transistor1[3] = { 0, 1, 0 };
static const bool transistor2[3] = { 1 ,0 ,0 };
void init(void) {
SystemInit(); // Initialize the System
// ---- Setup PLL for 48 MHz :) ----
RCC_DeInit();
RCC_PLLCmd(DISABLE);
RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_12);
// Flash: 1 WaitState for 24MHz < SysCLK < 48 MHz
FLASH_SetLatency(FLASH_Latency_1);
FLASH_PrefetchBufferCmd(ENABLE);
// Set ADC clock to sync PCLK/4->12MHz
RCC_ADCCLKConfig(RCC_ADCCLK_HSI14);
// and turn the PLL back on again
RCC_PLLCmd(ENABLE);
// set PLL as system clock source
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
// ---- End of Setup PLL for 48 MHz :) ----
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStruct;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
// ADC-init for Temperature probe
ADC_DeInit(ADC1);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // on demand
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_TRGO;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 12 bit right aligned
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
ADC_Init(ADC1, &ADC_InitStructure);
// ADC calibration; but not used as returned value ends nowhere now...
VREFINT_CAL = ADC_GetCalibrationFactor(ADC1);
ADC_Cmd(ADC1, ENABLE);
ADC_DiscModeCmd(ADC1, ENABLE);
// Resistor switches (PNP FET) on PA0+1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// R-Probe on PA2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// UART1: Configure PA9 and PA10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
USART_InitStruct.USART_BaudRate = 57600;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART1, &USART_InitStruct);
USART_Cmd(USART1, ENABLE);
RCC_GetClocksFreq(&Clocks);
}
int main (void) {
init();
sprintf(text, "STM32F030-Charger startup.\r\nHCLK is %ld MHz, PCLK %ld MHz, System %ld MHz, ADC %ld MHz.\r\n", (Clocks.HCLK_Frequency/1000000), (Clocks.PCLK_Frequency/1000000), (Clocks.SYSCLK_Frequency/1000000), (Clocks.ADCCLK_Frequency/1000000));
uart_tx(text);
charge_rate = 0;
if (transistor1[charge_rate]) GPIOA->BSRR = (GPIO_Pin_0); // Enable FET 1 (2.300 Ohm)
if (transistor2[charge_rate]) GPIOA->BSRR = (GPIO_Pin_1); // Enable FET 2 (1.150 Ohm)
while (1) {
int stage = read_adc();
int Vmax = (uint32_t)(2000*3280/(1<<12));
int Vprog = (uint32_t)(stage*3280/(1<<12));
int Ibat = (uint32_t) ((1000*Vprog/resistance[charge_rate]*1200) / 1000);
int percent = (uint32_t)(Vprog * 100/Vmax);
sprintf(text, "Charging with %d mA. (Vprog %dmV, %d%%.)\r\n", Ibat, Vprog, percent);
uart_tx(text);
Delay(10000000);
}
}
int read_adc(void) {
uint32_t temp = 0;
ADC_ChannelConfig(ADC1, ADC_Channel_2, ADC_SampleTime_13_5Cycles);
// throw away first result like on AVR? first value seems wrong.
ADC_StartOfConversion(ADC1);
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
for (uint8_t i = 0; i<16; i++) { // resampling
ADC_StartOfConversion(ADC1);
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
temp += ADC_GetConversionValue(ADC1);
}
return ( (temp>>4) );
}
void uart_tx(char *out) {
while (*out) {
while(!(USART1->ISR & USART_FLAG_TXE)) {
// Nothing, really.;
}
USART1->TDR = *out++;
}
}
void Delay(__IO uint32_t nCount) {
while(nCount--) {
}
}
The standard perhipheral library is a load of crap! It is extremely bloated and performs things an exteremely backwards way.
2) Use libopencm3 (formally libopenstm32), very well written, very easy to use with well written examples and a lot of support.
but when I need raw power, or smaller code, I will configure the registers myself.
A bit shorter no?
QuoteThe standard perhipheral library is a load of crap! It is extremely bloated and performs things an exteremely backwards way.Quote2) Use libopencm3 (formally libopenstm32), very well written, very easy to use with well written examples and a lot of support.
What's crap and what's not is quite subjective - not right or wrong.
Foundamentally, the use of libraries is a trade-off between many factors, speed / space and ease of use, documentation, reliability, .... There is no right or wrong answer here. Part of a designer's job is to assess the situation and figure out which way is better in a given application.Quotebut when I need raw power, or smaller code, I will configure the registers myself.
With that, why don't you implement the following:
1) boot up the chip in hsixpll, construct a random number by reading the lsb of an adc pin and transmit that via usart interrupt.
2) implement that using your direct register access + libopencm3.
We will see how much faster your code runs, how much smaller it is vs. the St library implementation. Then we can see if it is worth it.
QuoteA bit shorter no?
If you allow the use of a library, I can make it into one line, :).
libopencm3 has quite a lot of developers backing and using it,
many people, including myself, moved from the std lib because we found it sucked...
as I stated, it is rare.
#include "stm32f0xx.h"
#include <stdbool.h>
#include <stdio.h>
#include "main.h"
static char text[255];
RCC_ClocksTypeDef Clocks;
volatile uint8_t digit[4];
// 'database' of digits
static uint8_t lightup[10]={
0b00000011, // 0
0b10011111, // 1
0b00100101, // 2
0b00001101, // 3
0b10011001, // 4
0b01001001, // 5
0b01000001, // 6
0b00011111, // 7
0b00000001, // 8
0b00001001 }; // 9
void init(void) {
SystemInit(); // Initialize the System
// ---- Setup PLL for 48 MHz :) ----
RCC_DeInit();
RCC_PLLCmd(DISABLE);
RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_12);
// Flash: 1 WaitState for 24MHz < SysCLK < 48 MHz
FLASH_SetLatency(FLASH_Latency_1);
FLASH_PrefetchBufferCmd(ENABLE);
// Set ADC clock to sync PCLK/4->12MHz
RCC_ADCCLKConfig(RCC_ADCCLK_HSI14);
// and turn the PLL back on again
RCC_PLLCmd(ENABLE);
// set PLL as system clock source
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
// ---- End of Setup PLL for 48 MHz :) ----
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
// 7-seg on PA0-PA4
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// UART1: Configure PA9 and PA10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
USART_InitStruct.USART_BaudRate = 57600;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART1, &USART_InitStruct);
USART_Cmd(USART1, ENABLE);
RCC_GetClocksFreq(&Clocks);
// switch 7-seg on
GPIOA->BSRR = GPIO_Pin_0; // Vcc on PA0
GPIOA->BRR = GPIO_Pin_1; // GND on PA1
// PA2: SHCP, PA3: STCP; PA4: DS
}
int main (void) {
init();
sprintf(text, "STM32F030-7Seg startup.\r\nHCLK is %ld MHz, PCLK %ld MHz, System %ld MHz, ADC %ld MHz.\r\n", (Clocks.HCLK_Frequency/1000000), (Clocks.PCLK_Frequency/1000000), (Clocks.SYSCLK_Frequency/1000000), (Clocks.ADCCLK_Frequency/1000000));
uart_tx(text);
while (1) {
for (int i=0; i<10000; i++) {
int temp = i;
for (int j=3; j>=0; j--) {
digit[3-j] = temp % 10;
temp /= 10;
}
for (int k=0; k<2000; k++) {
show_digit();
}
}
}
}
void show_digit (void) {
int temp = 0;
for (int i=0; i<4; i++) {
temp = (((lightup[digit[i]]))<<8) | (1<<(i+4));
push_out(temp);
}
}
void push_out(int output) {
for (int i=0; i<16; i++) {
if (output & (1<<i)) {
GPIOA->BSRR = GPIO_Pin_4;
} else {
GPIOA->BRR = GPIO_Pin_4;
}
GPIOA->BSRR = GPIO_Pin_2;
GPIOA->BRR = GPIO_Pin_2;
}
GPIOA->BSRR = GPIO_Pin_3;
GPIOA->BRR = GPIO_Pin_3;
Delay(600);
}
void uart_tx(char *out) {
while (*out) {
while(!(USART1->ISR & USART_FLAG_TXE)) {
// Nothing, really.;
}
USART1->TDR = *out++;
}
}
void Delay(__IO uint32_t nCount) {
while(nCount--) {
}
}
I built a 4-digit-7-segment and wrote PoC code for the tiny F030.
#include "tmr14.h" //use tmr14
void show_digit(void); //update display
int main(void) {
...
//set up tmr14 to update led display periodically
tmr14_init(TMR_PS_100x, TMR_1ms); //tmr14 initialized to 1ms interval, 100x prescaler => 1 overflow every 100ms
tmr14_isr(show_digit); //install show_digit() as user isr
//done
this is STM32L152
The standard perhipheral library is a load of crap! It is extremely bloated and performs things an exteremely backwards way.You might enjoy "The other ST thread" where I've also been complaining about the STP, and positing some theories that the way it has been deployed is not the way that the original authors had in mind. In a simple example, I cut size of generated code by about 40% by rearranging the STP source to be "inline" rather than in a separate library. (starting about here: https://www.eevblog.com/forum/microcontrollers/one-dollar-one-minute-arm-development/msg516710/#msg516710 (https://www.eevblog.com/forum/microcontrollers/one-dollar-one-minute-arm-development/msg516710/#msg516710) )
That's how I know inlining, too. More like a #define or Macro, to insert a function completely at that space and reduce jumps, a bit like loop unrolling (which obviously is not reducing the code size).
Thus I'm interested to know how inlining is done to reduce codesize, not to bloat it. I miss that explanation on the other thread, I just read that functions are repeated in several classes of the SPL and thus some optimizations in that area would be possible.
functions are repeated in several classes of the SPL
(And so small functions which would result in 1-2 machine instructions would more likely be macros, won't they? I can't from top of my head think of having ever seen something like that as function :D )
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->BSRR = GPIO_Pin;
}
I went back to that thread where inlining cuts the code by 40%. I didn't see anything that supports it
#include "stm32f0xx_rcc.h" //clock routing used
#include "stm32f0xx_gpio.h" //gpio modules used
#include "stm32f0xx_adc.h" //adc module used
#include "stm32f0xx_usart.h" //usart used
#include "stm32f0xx_misc.h" //interrupts used
#ifdef DOINLINE
#include "stm32f0xx_rcc.c" //clock routing used
#include "stm32f0xx_gpio.c" //gpio modules used
#include "stm32f0xx_adc.c" //adc module used
#include "stm32f0xx_usart.c" //usart used
#endif
BillW-MacOSX-2<10307> make dannyn
/usr/local/armgcc/bin/arm-none-eabi-gcc -DSTM32F10X_MD=1 -mcpu=cortex-m3 -mthumb -O3 -ffunction-sections -fdata-sections -Wl,--gc-sections -gdwarf-2 -include assert.h -o danny_normal -DSTM32F030=1 \
-I normal danny.c \
normal/stm32f0xx_misc.c normal/system_stm32f0xx.c \
normal/stm32f0xx_usart.c normal/stm32f0xx_rcc.c \
normal/stm32f0xx_adc.c normal/stm32f0xx_gpio.c
/usr/local/armgcc/bin/arm-none-eabi-size danny_normal
text data bss dec hex filename
3288 1120 40 4448 1160 danny_normal
BillW-MacOSX-2<10308> make dannyi2
/usr/local/armgcc/bin/arm-none-eabi-gcc -DSTM32F10X_MD=1 -mcpu=cortex-m3 -mthumb -O3 -ffunction-sections -fdata-sections -Wl,--gc-sections -gdwarf-2 -include assert.h -o danny_i2 -DSTM32F030=1 \
-I normal -DDOINLINE danny.c \
normal/stm32f0xx_misc.c normal/system_stm32f0xx.c
/usr/local/armgcc/bin/arm-none-eabi-size danny_i2
text data bss dec hex filename
2900 1120 36 4056 fd8 danny_i2
#include <stm32f0xx.h>
#include "stm32f0xx_usart.h"
int main(void) {
USART_InitTypeDef USART_InitStruct;
USART_DeInit(USART1);
//USART_Init(USART1, &USART_InitStruct);
while(1) {
}
}
arm-none-eabi-size main.elf
text data bss dec hex filename
596 0 0 596 254 main.elf
Thread model: single
gcc version 4.8.4 20140526 (release) [ARM/embedded-4_8-branch revision 211358] (GNU Tools for ARM Embedded Processors)
arm-none-eabi-size main.elf
text data bss dec hex filename
1396 20 4 1420 58c main.elf
BillW-MacOSX-2<10344> make nostartn
/usr/local/armgcc/bin/arm-none-eabi-gcc -DSTM32F10X_MD=1 -mcpu=cortex-m3 -mthumb -O3 -ffunction-sections -fdata-sections -Wl,--gc-sections -gdwarf-2 -include assert.h -o test_normal \
-nostartfiles \
-I normal main.c normal/stm32f10x_usart.c normal/stm32f10x_rcc.c start.c
/usr/local/armgcc/bin/arm-none-eabi-size test_normal
text data bss dec hex filename
592 36 0 628 274 test_normal
BillW-MacOSX-2<10345> make nostarti
/usr/local/armgcc/bin/arm-none-eabi-gcc -DSTM32F10X_MD=1 -mcpu=cortex-m3 -mthumb -O3 -ffunction-sections -fdata-sections -Wl,--gc-sections -gdwarf-2 -include assert.h -o test_inline \
-nostartfiles \
-I inlines main.c start.c
/usr/local/armgcc/bin/arm-none-eabi-size test_inline
text data bss dec hex filename
352 36 0 388 184 test_inline
the stm32f7?
more explicitThanks. That does help a lot.
USART_TypeDef *uart;
uart=USART2;
:
myUSART_DeInit(uart);
You should have myUSART_DeInit(USART2);
I'm a little surprised (and disappointed) that gcc doesn't manage to do this optimization even for your original code. Clearly uart has a constant value and is not volatile or anything; your code and the code with an explicitly constant argument REALLY ought to compile the same :-(( plain )
text data bss dec hex filename
1244 1080 32 2356 934 a.out
-DCONSTANT
1236 1080 28 2344 928 a.out
-DMANY
1256 1080 32 2368 940 a.out
-DMANY -DCONSTANT
1248 1080 28 2356 934 a.out
-DINLINES
1060 1080 32 2172 87c a.out
-DINLINES -DCONSTANT
1044 1080 28 2152 868 a.out
-DINLINES -DMANY
1384 1080 32 2496 9c0 a.out
-DINLINES -DMANY -DCONSTANT
1084 1080 28 2192 890 a.out
void exit(int r) {while(1);}
Apparently the standard runtime defaults to a fancy version of exit that calls registered exit procedures. And that pulls in code to register those procs. And support functions. 528 bytes worth of code plus over 1000 bytes of "data" to support something that shouldn't happen in an embedded system (calling exit() or allowing main() to return.) Sigh.text data bss dec hex filename
4914 124 568 5606 15e6 stm32-7seg.elf
text data bss dec hex filename
4914 124 568 5606 15e6 stm32-7seg.elf
text data bss dec hex filename
4914 124 568 5606 15e6 stm32-7seg.elf
BUILD FAILED
java.lang.OutOfMemoryError: PermGen space
Total time: 1 second
It seems to add about 2M to the memory usage for each build, and craps out around 190MB total (according to the task manager.) that seems low, given that the VM has 2G and the system claims 1.5G is still free when CoIDE stops working. Grr.Hmm. So I installed CoIDE and the Windows ARM compiler (4.8.4!) on my windows XP VM, and it does indeed have different behavior WRT exit()/etc. It also seems to have a memory leak, so that after a dozen or so "rebuild" steps, I get:Code: [Select]BUILD FAILED
It seems to add about 2M to the memory usage for each build, and craps out around 190MB total (according to the task manager.) that seems low, given that the VM has 2G and the system claims 1.5G is still free when CoIDE stops working. Grr.
java.lang.OutOfMemoryError: PermGen space
Total time: 1 second
--launcher.XXMaxPermSize
256M
-vmargs
-Xms60m
-Xmx512m
-XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled
There's a fix for thatI was hoping there was, but not looking forward to trying to track it down.
LM4F is the supposed Cortex M4 based successorBriefly. TI gave up the LM prefix and the ARM microcontrollers are now "TIVA TM4Cxxxx" The LM4F based "stellaris launcpad" was replaced with the "Tiva Launchpad" and has a TM4C123GH6PM to replace the LM4F120H5QR. They're ALMOST the same.
allegedly cheap low-pin-count versions are not yet available.
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
// Initialize I2C (PB6 = SCL, PB7 =SDA)
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_1);
// I2C Configure pins: SCL and SDA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_DeInit(I2C1);
I2C_Cmd(I2C1, DISABLE);
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStructure.I2C_DigitalFilter = 0x00;
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_Timing = 0xB0420F13; // magic!
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
I guess this works with a lot of I2C chips:
This thing starts beeping with the slightest movement, really nerve wasting.
avg += (new_data - avg) >> n;
avg = avg * (1-weight) + new_data * weight;
"audio visual bite indicator"
Wanted to fix the DS1307 with soldering the crystal to the GND area and maybe replace it with a better suiting one (next to solder an additional 10µF tantal + 0.1µF ceramic capacitor to Vcc; also shortening the jumping wires from 8" to way less length for the SDA/SCL lines) as first attempt before throwing those parts into trash. :D
Maybe you have the wrong crystal match?
would sum up to ~4s/day
STM's built-in RTC
6.3.6 RTC wakeup from low-power mode
The RTC can be used to wakeup the MCU from low-power mode by means of the RTC
alarm. For this purpose, two of the three alternative RTC clock sources can be selected by
programming the RTCSEL[1:0] bits in the RTC domain control register (RCC_BDCR):
? Low-power 32.768 kHz external crystal oscillator (LSE OSC)
This clock source provides a precise time base with very low-power consumption (less
than 1µA added consumption in typical conditions)
? Low-power internal RC Oscillator (LSI)
This clock source has the advantage of saving the cost of the 32.768 kHz crystal. This
internal RC Oscillator is designed to add minimum power consumption.
To wakeup from Stop mode with an RTC alarm event, it is necessary to:
? Configure the EXTI Line 17 to be sensitive to rising edge
? Configure the RTC to generate the RTC alarm
To wakeup from Standby mode, there is no need to configure the EXTI Line 17.
What bothers me most with 1117 is the minimum load of 5-10mA.Lets be clear here (for my understanding at least).
LDO | Vout *1 | Current *2 |
PAM3101 | 3.292V | 59,8µA |
RT9166 | 3.285V | 6.3µA |
MCP1825S | 3.335V | 44.1µA |
Set up HSIxPLL:
...
That's 64 million reasons to get this little bugger, :)
RCC_DeInit(); //reset rcc
RCC_PLLCmd(DISABLE); //disable PLL
RCC_HSICmd(ENABLE); //enable hsi;
RCC_HCLKConfig(RCC_SYSCLK_Div1); //set sysclk divider
RCC_PLLConfig(RCC_CFGR_PLLSRC_HSI_Div2, RCC_PLLMul_12); //configure pll / divider. _x=[2..16]
RCC_PLLCmd(ENABLE); //enable pll
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) continue; //wait for pll to be ready
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //set pll as sysclk
while (RCC_GetSYSCLKSource() != RCC_CFGR_SWS_PLL/*0x08*/) continue; //wait for PLL to be ready
SystemCoreClockUpdate(); //update SystemCoreClock
// ---- Setup PLL for 48 MHz :) ----
RCC_DeInit();
RCC_PLLCmd(DISABLE);
RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_12);
// Flash: 1 WaitState for 24MHz < SysCLK < 48 MHz
FLASH_SetLatency(FLASH_Latency_1);
FLASH_PrefetchBufferCmd(ENABLE);
// Set ADC clock to internal HSI 14MHz
RCC_ADCCLKConfig(RCC_ADCCLK_HSI14);
// and turn the PLL back on again
RCC_PLLCmd(ENABLE);
// set PLL as system clock source
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
// ---- End of Setup PLL for 48 MHz :) ----
My leds keep flashing, so the MCU keeps crashing and restarting.
After programming the MCU also disconnects from programmer, picture added.
The only problem that i had, was that i couldn't use the flash functions.
I've added #include "stm32f0xx_flash.h", with no result. My compiler does not find the routines in the corresponding .c file.
Thanks for the help, i'll continue my search..
LDO | Vout *1 | Current *2 |
PAM3101 | 3.292V | 59,8µA |
RT9166 | 3.285V | 6.3µA |
MCP1825S | 3.335V | 44.1µA |
MCP1700 | 3.283V | 1.3µA |
Thanks for the help, i'll continue my search..
Liked the sublime style. Did you do it in eclipse or just used sublime as the external editor in eclipse?
QuoteMy leds keep flashing, so the MCU keeps crashing and restarting.
Not sure how your code works so not much can be read from the fact that "the led keep flashing"QuoteAfter programming the MCU also disconnects from programmer, picture added.
Typically from the swd pins being used by the code.QuoteThe only problem that i had, was that i couldn't use the flash functions.
I've added #include "stm32f0xx_flash.h", with no result. My compiler does not find the routines in the corresponding .c file.
Include the .c files in your project and have the .h files in the include path.
If I were you, I would post a minimalist but complete piece of code so that others know what you are talking about.
As to wait state, I ran a stm32f030f up to 50+Mhz on 0 wait state so it is fairly tolerant.
#include <stdio.h>
#include "stm32f0xx.h"
#include "stm32f0xx_flash.h"
void delay(long int delaytime){
for(long int i=0; i<(delaytime*10000000);i++){
}
}
int
main(int argc, char* argv[])
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitTypeDef gis;
gis.GPIO_Mode = GPIO_Mode_OUT;
gis.GPIO_OType = GPIO_OType_PP;
gis.GPIO_Pin = GPIO_Pin_12;
gis.GPIO_PuPd = GPIO_PuPd_NOPULL;
gis.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&gis);
// ---- Setup PLL for 48 MHz :) ----
RCC_DeInit();
RCC_PLLCmd(DISABLE);
RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_2);
// Flash: 1 WaitState for 24MHz < SysCLK < 48 MHz
//FLASH_SetLatency(FLASH_Latency_1);
//FLASH_PrefetchBufferCmd(ENABLE);
// Set ADC clock to internal HSI 14MHz
RCC_ADCCLKConfig(RCC_ADCCLK_HSI14);
// and turn the PLL back on again
RCC_PLLCmd(ENABLE);
// set PLL as system clock source
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
// ---- End of Setup PLL for 48 MHz :) ----
// Infinite loop
while (1)
{
delay(100);
GPIOA->BSRR = GPIO_Pin_12;
delay(100);
GPIOA->BRR = GPIO_Pin_12;
}
return 0;
}
void RCC_PLLCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->CR |= RCC_CR_PLLON;
}
else
{
RCC->CR &= ~RCC_CR_PLLON;
}
}
I step through my code, everything goes well, until my PLL-bit gets set and then i lose everything. ->>RCC->CR |= RCC_CR_PLLON;built up a MCP1700 today. This one is amazing!Available in TO92, too!
I don't have your chip so I cannot tell you how it will work on a F05.
However, I tried the following on a F03 chip and it works as expected.
Here is the code:Code: [Select]#include <stm32f0xx.h> //stm32f030f4
#include "stm32f0xx_rcc.h" //we use rcc
#include "gpio.h"
//connection
#define LED_PORT GPIOA
#define LED_A (1<<1)
#define LED_C (1<<2)
void SystemCoreClockHSIPLL2(uint32_t RCC_PLLMul_x) {
RCC_DeInit(); //reset rcc
RCC_PLLCmd(DISABLE); //disable PLL
RCC_HSICmd(ENABLE); //enable hsi;
RCC_HCLKConfig(RCC_SYSCLK_Div1); //set sysclk divider
//RCC_PCLK1Config(RCC_HCLK_Div1); //set pclk1/2 dividers
//RCC_PCLK2Config(RCC_HCLK_Div1);
/**
* @brief Configures the PLL clock source and multiplication factor.
* @note This function must be used only when the PLL is disabled.
*
* @param RCC_PLLSource: specifies the PLL entry clock source.
* This parameter can be one of the following values:
* @arg RCC_PLLSource_HSI_Div2: HSI oscillator clock selected as PLL clock source
* @arg RCC_PLLSource_PREDIV1: PREDIV1 clock selected as PLL clock entry
* @arg RCC_PLLSource_HSI48 HSI48 oscillator clock selected as PLL clock source, applicable only for STM32F072 devices
* @arg RCC_PLLSource_HSI: HSI clock selected as PLL clock entry, applicable only for STM32F072 devices
* @note The minimum input clock frequency for PLL is 2 MHz (when using HSE as
* PLL source).
*
* @param RCC_PLLMul: specifies the PLL multiplication factor, which drive the PLLVCO clock
* This parameter can be RCC_PLLMul_x where x:[2,16]
*
* @retval None
*/
RCC_PLLConfig(RCC_CFGR_PLLSRC_HSI_Div2, RCC_PLLMul_x); //configure pll / divider. _x=[2..16]
RCC_PLLCmd(ENABLE); //enable pll
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) continue; //wait for pll to be ready
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //set pll as sysclk
while (RCC_GetSYSCLKSource() != RCC_CFGR_SWS_PLL/*0x08*/) continue; //wait for PLL to be ready
SystemCoreClockUpdate(); //update SystemCoreClock
}
//delays some
void delay(uint32_t dly) {
while (dly--) NOP();
}
int main(void) {
mcu_init();
SystemCoreClockHSIPLL2(RCC_PLLMul_12); //go to 48Mhz
PIN_SET(LED_PORT, LED_A); PIN_OUT(LED_PORT, LED_A);
PIN_CLR(LED_PORT, LED_C); PIN_OUT(LED_PORT, LED_C);
while(1) {
PIN_FLP(LED_PORT, LED_A | LED_C);
delay(100000);
}
}
In addition to SystemCoreClock, the speed at which the led is blinked varies visibly as I change the PLL multiplier.
So your issues are probably somewhere else.
#include <stm32f0xx.h> //stm32f030f4
#include "stm32f0xx_rcc.h" //we use rcc
#include "stm32f0xx_gpio.h"
//connection
#define LED_PORT GPIOF
#define LED_A (1<<6)
#define LED_C (1<<7)
void SystemCoreClockHSIPLL2(uint32_t RCC_PLLMul_x) {
RCC_DeInit(); //reset rcc
RCC_PLLCmd(DISABLE); //disable PLL
RCC_HSICmd(ENABLE); //enable hsi;
RCC_HCLKConfig(RCC_SYSCLK_Div1); //set sysclk divider
//RCC_PCLK1Config(RCC_HCLK_Div1); //set pclk1/2 dividers
//RCC_PCLK2Config(RCC_HCLK_Div1);
/**
* @brief Configures the PLL clock source and multiplication factor.
* @note This function must be used only when the PLL is disabled.
*
* @param RCC_PLLSource: specifies the PLL entry clock source.
* This parameter can be one of the following values:
* @arg RCC_PLLSource_HSI_Div2: HSI oscillator clock selected as PLL clock source
* @arg RCC_PLLSource_PREDIV1: PREDIV1 clock selected as PLL clock entry
* @arg RCC_PLLSource_HSI48 HSI48 oscillator clock selected as PLL clock source, applicable only for STM32F072 devices
* @arg RCC_PLLSource_HSI: HSI clock selected as PLL clock entry, applicable only for STM32F072 devices
* @note The minimum input clock frequency for PLL is 2 MHz (when using HSE as
* PLL source).
*
* @param RCC_PLLMul: specifies the PLL multiplication factor, which drive the PLLVCO clock
* This parameter can be RCC_PLLMul_x where x:[2,16]
*
* @retval None
*/
RCC_PLLConfig(RCC_CFGR_PLLSRC_HSI_Div2, RCC_PLLMul_x); //configure pll / divider. _x=[2..16]
RCC_PLLCmd(ENABLE); //enable pll
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) continue; //wait for pll to be ready
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //set pll as sysclk
while (RCC_GetSYSCLKSource() != RCC_CFGR_SWS_PLL/*0x08*/) continue; //wait for PLL to be ready
SystemCoreClockUpdate(); //update SystemCoreClock
}
//delays some
void delay(uint32_t dly) {
while (dly--) asm("NOP");
}
int main(void) {
SystemCoreClockHSIPLL2(RCC_PLLMul_12); //go to 48Mhz
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE);
GPIO_InitTypeDef gis;
gis.GPIO_Mode = GPIO_Mode_OUT;
gis.GPIO_OType = GPIO_OType_PP;
gis.GPIO_Pin = LED_A | LED_C;
gis.GPIO_PuPd = GPIO_PuPd_NOPULL;
gis.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED_PORT,&gis);
LED_PORT->ODR &= ~(LED_A | LED_C);
while(1) {
LED_PORT->ODR ^= (LED_A | LED_C);
delay(100000);
}
}
the chip resets when i enable the PLL..Can you implement individual fault handlers, and figure out WHY it's resetting (and exactly where)?
#include <stm32f0xx.h> //stm32f030f4
#include "stm32f0xx_rcc.h" //we use rcc
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_flash.h"
//connection
#define LED_PORT GPIOC
#define LED_A (1<<8)
#define LED_C (1<<9)
void SystemCoreClockHSIPLL2(uint32_t RCC_PLLMul_x) {
RCC_DeInit(); //reset rcc
RCC_PLLCmd(DISABLE); //disable PLL
RCC_HSICmd(ENABLE); //enable hsi;
RCC_HCLKConfig(RCC_SYSCLK_Div1); //set sysclk divider
//RCC_PCLK1Config(RCC_HCLK_Div1); //set pclk1/2 dividers
//RCC_PCLK2Config(RCC_HCLK_Div1);
/**
* @brief Configures the PLL clock source and multiplication factor.
* @note This function must be used only when the PLL is disabled.
*
* @param RCC_PLLSource: specifies the PLL entry clock source.
* This parameter can be one of the following values:
* @arg RCC_PLLSource_HSI_Div2: HSI oscillator clock selected as PLL clock source
* @arg RCC_PLLSource_PREDIV1: PREDIV1 clock selected as PLL clock entry
* @arg RCC_PLLSource_HSI48 HSI48 oscillator clock selected as PLL clock source, applicable only for STM32F072 devices
* @arg RCC_PLLSource_HSI: HSI clock selected as PLL clock entry, applicable only for STM32F072 devices
* @note The minimum input clock frequency for PLL is 2 MHz (when using HSE as
* PLL source).
*
* @param RCC_PLLMul: specifies the PLL multiplication factor, which drive the PLLVCO clock
* This parameter can be RCC_PLLMul_x where x:[2,16]
*
* @retval None
*/
FLASH_SetLatency(FLASH_Latency_1);
FLASH_PrefetchBufferCmd(ENABLE);
RCC_PLLConfig(RCC_CFGR_PLLSRC_HSI_Div2, RCC_PLLMul_x); //configure pll / divider. _x=[2..16]
RCC_PLLCmd(ENABLE); //enable pll
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) continue; //wait for pll to be ready
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //set pll as sysclk
while (RCC_GetSYSCLKSource() != RCC_CFGR_SWS_PLL/*0x08*/) continue; //wait for PLL to be ready
SystemCoreClockUpdate(); //update SystemCoreClock
}
//delays some
void delay(uint32_t dly) {
while (dly--) __asm("NOP");
}
int main(void) {
SystemCoreClockHSIPLL2(RCC_PLLMul_12); //go to 48Mhz
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIO_InitTypeDef gis;
gis.GPIO_Mode = GPIO_Mode_OUT;
gis.GPIO_OType = GPIO_OType_PP;
gis.GPIO_Pin = LED_A | LED_C;
gis.GPIO_PuPd = GPIO_PuPd_NOPULL;
gis.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED_PORT,&gis);
LED_PORT->ODR &= ~(LED_A);
LED_PORT->ODR |= (LED_C);
while(1) {
LED_PORT->ODR ^= (LED_A | LED_C);
delay(1000000);
}
}
If the code works again on your f051-disco, the problem source should be clear.
Also, I read somewhere that current Coocox is buggy. a few versions back and the functions work as expected. You should either try that, or setup your own Eclipse environment with gnu-arm-eabi compilers and STM plug-ins. Then you can use the STM standard peripheral lib in the last version, which should work flawless.
_Or_ you could open an own thread, as this is again and continuesly quite off-topic for STM32 ghetto style and a way more concrete problem with non-ghetto STM ;)
I've read somewhere that some faults pull down the reset line,
LDO | Vout | mAin | mAout | NoLoad µA | mWin | mWout | Eff % |
MCP1700 (http://ww1.microchip.com/downloads/en/DeviceDoc/20001826C.pdf) | 3.283 | 1.89 | 1.88 | 1.3 | 7,37 | 6,17 | 83,71 |
PAM3101 (http://www.diodes.com/datasheets/PAM3101.pdf) | 3.303 | 1.96 | 1.88 | 57.6 | 7,65 | 6,21 | 81,21 |
MCP1825S (http://ww1.microchip.com/downloads/en/devicedoc/22056b.pdf) | 3.334 | 1.97 | 1.93 | 44.0 | 7,68 | 6,43 | 83,73 |
RT9166 (http://www.100y.com.tw/pdf_file/38-Richtek-RT9166.pdf) | 3.260 | 1.87 | 1.86 | 6.1 | 7,29 | 6,06 | 83,12 |
simply the ratio of A in versus A out?
Cheapest offers I could find for the LT1073 (http://cds.linear.com/docs/en/datasheet/1073fa.pdf):I would not trust such an offer. An ic that regularly would cost $4 /100 pcs now for $1 that smells..... Could be excess stock but I had my share with fake chips.
http://www.aliexpress.com/item/LT1073/2011254186.html (http://www.aliexpress.com/item/LT1073/2011254186.html)
F030->F051; that's where I think problems could arise (at least if you use a binary for the bigger µC on the smaller one).
Step-up | Vout | mAin | mAout | NoLoad µA | mWin | mWout | Eff % |
NCP1402 (http://www.onsemi.com/pub/Collateral/NCP1402-D.PDF) | 3.32 | 75 | 16 | 18.5 | 93.75 | 53.12 | 56.66 |
(1N4148) | 3.32 | 100 | 25 | 18.5 | 125.00 | 83.00 | 66.40 |
TPS61097A-33 (http://www.ti.com/lit/ds/symlink/tps61097a-33.pdf) | 3.28 | 58 | 16 | ~0mA | 72.50 | 52.48 | 72.39 |
3.28 | 85 | 25 | ~0mA | 106.25 | 82.00 | 77.18 |
LDO | Vout | mAin | mAout | NoLoad µA | mWin | mWout | Eff % |
MCP1700 (http://ww1.microchip.com/downloads/en/DeviceDoc/20001826C.pdf) | 3.283 | 1.89 | 1.88 | 1.3 | 7,37 | 6,17 | 83,71 |
PAM3101 (http://www.diodes.com/datasheets/PAM3101.pdf) | 3.303 | 1.96 | 1.88 | 57.6 | 7,65 | 6,21 | 81,21 |
MCP1825S (http://ww1.microchip.com/downloads/en/devicedoc/22056b.pdf) | 3.334 | 1.97 | 1.93 | 44.0 | 7,68 | 6,43 | 83,73 |
RT9166 (http://www.100y.com.tw/pdf_file/38-Richtek-RT9166.pdf) | 3.260 | 1.87 | 1.86 | 6.1 | 7,29 | 6,06 | 83,12 |
Charge pump | Vout | mAin | mAout | NoLoad µA | mWin | mWout | Eff % |
TPS60302 (http://www.ti.com/lit/ds/symlink/tps60302.pdf) | 3.35 | 71 | 17 | 33 | 88.75 | 56.93 | 64.15 |
3.35 | 92 | 24 | 33 | 115.00 | 80.38 | 69,89 |
fail to get a guide to setup Eclipse/SDCC (which supports STM8 - allegedly)
SDCC does not have the ability to trim unused code - stunning in this time and age, if you ask me. So the only solution is for you to only include those functions in your project.
This is the sort of vendor library code that I really dislike. All that to set up the clock; a feature that most programmers really don't care that much about at the detailed level. You should be able to say "my crystal is xxx and I want the cpu to run at yyy", and there should be a function that goes off and DOES that without worrying about PLL inputs and multipliers and such. And it should generate pretty minimal code; not dragging in a lot of libraries.Code: [Select]RCC_DeInit(); //reset rcc
RCC_PLLCmd(DISABLE); //disable PLL
RCC_HSICmd(ENABLE); //enable hsi;
RCC_HCLKConfig(RCC_SYSCLK_Div1); //set sysclk divider
RCC_PLLConfig(RCC_CFGR_PLLSRC_HSI_Div2, RCC_PLLMul_12); //configure pll / divider. _x=[2..16]
RCC_PLLCmd(ENABLE); //enable pll
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) continue; //wait for pll to be ready
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //set pll as sysclk
while (RCC_GetSYSCLKSource() != RCC_CFGR_SWS_PLL/*0x08*/) continue; //wait for PLL to be ready
SystemCoreClockUpdate();
00000000 <main>:
0: e7fe b.n 0 <main>
2: bf00 nop
(you're right; there is nothing there. Because operation off of the 8MHz internal clock is the default state.)Crystal: 8000000, Desired: 72000000
00000000 <main>:
0: bf00 nop
00000002 <PICK_HSE>:
2: bf00 nop
00000004 <HSE_ON>:
4: 4b12 ldr r3, [pc, #72] ; (50 <Clock_done+0x2>)
6: 681a ldr r2, [r3, #0]
8: 4619 mov r1, r3
a: f442 3280 orr.w r2, r2, #65536 ; 0x10000
e: 601a str r2, [r3, #0]
10: 680a ldr r2, [r1, #0]
12: 4b0f ldr r3, [pc, #60] ; (50 <Clock_done+0x2>)
14: 0390 lsls r0, r2, #14
16: d5fb bpl.n 10 <HSE_ON+0xc>
00000018 <Latency2>:
18: 4a0e ldr r2, [pc, #56] ; (54 <Clock_done+0x6>)
1a: 6811 ldr r1, [r2, #0]
1c: f041 0102 orr.w r1, r1, #2
20: 6011 str r1, [r2, #0]
22: 685a ldr r2, [r3, #4]
24: f442 6280 orr.w r2, r2, #1024 ; 0x400
28: 605a str r2, [r3, #4]
0000002a <PLL_9>:
2a: 685a ldr r2, [r3, #4]
2c: f442 12e8 orr.w r2, r2, #1900544 ; 0x1d0000
30: f042 0202 orr.w r2, r2, #2
34: 605a str r2, [r3, #4]
00000036 <PLL_CR>:
36: 681a ldr r2, [r3, #0]
38: f042 7280 orr.w r2, r2, #16777216 ; 0x1000000
3c: 601a str r2, [r3, #0]
0000003e <PLL_SPIN>:
3e: 6819 ldr r1, [r3, #0]
40: 4a03 ldr r2, [pc, #12] ; (50 <Clock_done+0x2>)
42: 0189 lsls r1, r1, #6
44: d5fb bpl.n 3e <PLL_SPIN>
00000046 <USE_PLL>:
46: 6853 ldr r3, [r2, #4]
48: f043 0302 orr.w r3, r3, #2
4c: 6053 str r3, [r2, #4]
0000004e <Clock_done>:
4e: e7fe b.n 4e <Clock_done>
50: 40021000 .word 0x40021000
54: 40022000 .word 0x40022000
(The nop's are for testing purposes, so that the generated labels actually show up in the disassembly.)This is the sort of vendor library code that I really dislike.Well AFAIAC this maps directly on the datasheet/ ref. manual and allows all the flexibility that may be required by a user, such as dynamic clock alterations for some functions, PLL changes etc.
This optimization is something any modern linker (especially one for small platforms like SDCC) should be taking care of already.
It basically renders the compiler not usable for small devices.
I think those 003s are actually 103s marked down.
/* STM32F030F4P6 chinese board application
* slave for Single-wire half-duplex communication
* waits for the master's request, then
* - converts the corresponding adc channel
* - reads the corresponding io pin
* - put the results into a byte and send the byte while setting an rs485 driver output enable
*
*
*/
#include <stdio.h>
#include <stm32f0xx.h>
#include <system_stm32f0xx.h>
#include <stm32f0xx_gpio.h>
#include <stm32f0xx_rcc.h>
#include <stm32f0xx_adc.h>
#include "stm32f0xx_misc.h"
#include "stm32f0xx_usart.h"
void adc_conv_s();
void gpio_init();
void adc_init ();
void usart_init();
volatile uint16_t user;
volatile uint16_t user1 = 110;
volatile uint8_t tab_speed[] = {0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,39,41,43,45,47,49,51,53,55,57,59,61,63,63,63,63,63,1,1,1,1};
volatile uint8_t usart_rx_d;
volatile uint8_t usart_tx_d;
int main (void) {
gpio_init();
adc_init ();
usart_init();
while (1) {
}
}
void USART1_IRQHandler(void)
{
GPIOA->BRR = GPIO_Pin_10; // Set PA10 Low -> rs485 Driver Output Disable
usart_tx_d = 128+64;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
/* Read one byte from the receive data register */
usart_rx_d = USART_ReceiveData(USART1);
switch (usart_rx_d) {
case 0x24:
ADC1->CHSELR = 1<<0;
if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4)) {usart_tx_d = 128;}
adc_conv_s();
break;
case 0x25:
ADC1->CHSELR = 1<<1;
if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5)) {usart_tx_d = 128;}
adc_conv_s();
break;
case 0x26:
ADC1->CHSELR = 1<<2;
if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7)) {usart_tx_d = 128;}
adc_conv_s();
break;
case 0x27:
ADC1->CHSELR = 1<<3;
if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)) {usart_tx_d = 128;}
adc_conv_s();
break; }
}
}
void adc_conv_s()
{
ADC_StartOfConversion(ADC1);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN)); /* Wait the ADCEN flag */ // why 2 times ?
GPIOA->BSRR = GPIO_Pin_10; // Set PA10 HIGH -> rs485 Driver Output Enable
ADC_StartOfConversion(ADC1);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN)); /* Wait the ADCEN flag */
usart_rx_d = ADC_GetConversionValue(ADC1);
usart_rx_d = tab_speed[usart_rx_d/2];
usart_tx_d += usart_rx_d;
USART_SendData(USART1, usart_tx_d );
}
void gpio_init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_7); // input BUTTON S1,S2,S3
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure); // Initialises the GPIOA
GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_1); // input BUTTON 4
GPIO_Init(GPIOB, &GPIO_InitStructure); // Initialises the GPIOB
}
void adc_init (void) {
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
/* GPIOC Periph clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
/* ADC1 Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* Configure ADC Channel0 to 3 as analog input */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* ADC1 Configuration *******************************************************/
ADC_DeInit(ADC1);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_8b; /* Configure the ADC1 with a resolution equal to 8 bits*/
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_ChannelConfig(ADC1, ADC_Channel_0 , ADC_SampleTime_239_5Cycles); /* 239.5 Cycles as sampling time */
ADC_GetCalibrationFactor(ADC1); /* ADC Calibration */
ADC_Cmd(ADC1, ENABLE); /* Enable ADCperipheral */
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN)); /* Wait the ADCEN flag */
ADC_ChannelConfig(ADC1, ADC_Channel_0 , ADC_SampleTime_13_5Cycles); /* set the sample time */
// end of adc init code ...
}
void usart_init(void)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); /* Enable GPIO clock */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); /* Connect PXx to USARTx_Tx */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; /* Configure USART Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; /* Configure USART Rx as simple output function push-pull */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); /* Enable USART clock */
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200; /* USART configuration */
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART1->CR3 |= 8; // set HDSEL -> Single-wire half-duplex communication
USART_Cmd(USART1, ENABLE); /* Enable USART */
NVIC_EnableIRQ(USART1_IRQn); //
NVIC_SetPriority(USART1_IRQn, 0); //
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
// end of usart init code ...
}
/*
1 BOOT0
2 OSC_IN (PF0)
3 OSC_OUT (PF1)
4 NRST
5 VDD_A
6 PA0 USART1_CTS ; ADC_IN0,RTC_TAMP2,WKUP1
7 PA1 USART1_RTS,EVENTOUT ; ADC_IN1
8 PA2 USART1_TX ; ADC_IN2
9 PA3 USART1_RX ; ADC_IN3
10 PA4 SPI1_NSS,USART1_CK,TIM14_CH1 ; ADC_IN4
11 PA5 SPI1_SCK ; ADC_IN5
12 PA6 SPI1_MISO,TIM3_CH1,TIM1_BKIN,TIM16_CH1,EVENTOUT ; ADC_IN6
13 PA7 SPI1_MOSI,TIM3_CH2,TIM14_CH1,TIM1_CH1N,TIM17_CH1,EVENTOUT ; ADC_IN7
14 PB1 TIM3_CH4,TIM14_CH1,TIM1_CH3N ; ADC_IN9
15 VSS
16 VDD
17 PA9 USART1_TX,TIM1_CH2,I2C1_SCL
18 PA10 USART1_RX,TIM1_CH3,TIM17_BKIN,I2C1_SDA
19 PA13 IR_OUT,SWDIO
20 PA14 SWCLK
p1:
a4 button0 (led)-jumper-gnd
a3 adc3
a2 adc2
a1 adc1
a0 adc0
vdda
nrst
osc/o
osc/i
boot0
p2:
5v
3v3
a5 button1
a6 (b0t0)
a7 button2
b1 button3
a9 tx
a10 rx
a13 dio
a14 clk
j3:
gnd
tx tx/rx network
rx network -> rs485 Driver Output Enable
3v3
j4:
gnd
clk
dio
3v3
jumpers:
led
b0t0
vdda
*/
/* swd (jlink):
* bas :
* vert sous 1ère pin encoche
* haut (encoche) :
* jaune 2ème pin encoche
* orange à droite de jaune
* rouge dernière pin (sous triangle)
*/
the price should be less than 2$
Okay, you guys are gonna kill me for this..Wow ! thanks for this post !
VDDA wasn't connected on my board...
The good news is, i will shut up now because it's solved :).
Thanks for the support :-+