Newbie attempting to play with Fuse Settings!?

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I know this probably isn't something a newbie does but I'm trying to learn as much as I can and will need to know this eventually.

 

MY SOURCES:

I'm read the following tutorials on Fuse Settings in relation to changing the clock frequency on my ATmega328P Xplained Mini board. 

Introduction to Fuses (http://www.ladyada.net/learn/avr/fuses.html)

Section 9 of the chip datasheet (http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf)

Section 2.2 of User Guide for ATmega328P Xplained mini (http://www.atmel.com/Images/Atmel-42287-ATmega328P-Xplained-Mini-User-Guide_UserGuide.pdf)

_____________________________________________________________________________________

 

WHAT I'M TRYING TO DO:

Eventually, i'm going to be designing a board that uses a real time clock for input into a ATmega328P chip. So I would like to gain relevant knowledge with fuse settings "safely" using my Xplained Mini. Some major concepts I can think of are as follows...

1.) How to change the fuses to select different clock frequencies by Atmel Studio 6.2 tools or by direct assembly coding

2.) Knowing what fuses to change such as CKSEL0 through CKSEL3, SUT0 throughSUT1, and others i'm not aware

3.) How to change the pre scale value.  

4.) How to verify/test what fuses are previously set and how I might trouble shoot with using a scope 

_____________________________________________________________________________________

 

MY CURRENT SETUP AND WHAT I'VE TRIED

 

In the User Guide of my board under section 2.2(Clock Distribution) it says the following "The ATmega32U4 (mEDBG) has an external 16MHz XTAL. The ATmega32U4 provides an external 16MHz clock to the ATmega328P (Target).". 

 

I verified this by looking at the design documentation (see attachment "Design") I'll go ahead and attach the complete Design PDF in case you want a more detailed look. The 32U chip must be in charge of programming the 328P chip and providing the external 16MHz clock to the target (328P chip) In the design I see that this external clock is connect to the target (328P) on PB6 TOSC1/XTAL1. From reading section 9.2 in the 328P datasheet under Table 9-1(Device Clocking Options Select) I assume that the External Clock is being used. I don't understand when it defines a column as CKSEL3...0 and for external clock it says 0000 is the value set for CKSEL3...0. That confuses me. I guess i've been reading registers these past few days so i'm expecting something like bit 0 bit1 ect ect. Not understanding this fuse nomenclature. I've opened up the device file M328PDEF.INC and found a few interesting sections. I see there is a reference variable I can use to set them but still unsure and nervous on how to do it using code and where to exactly put this code in my .asm file. These declarations are as follows in case your wondering what I'm talking about...

; OSCCAL - Oscillator Calibration Value
.equ	CAL0	= 0	; Oscillator Calibration Value Bit0
.equ	CAL1	= 1	; Oscillator Calibration Value Bit1
.equ	CAL2	= 2	; Oscillator Calibration Value Bit2
.equ	CAL3	= 3	; Oscillator Calibration Value Bit3
.equ	CAL4	= 4	; Oscillator Calibration Value Bit4
.equ	CAL5	= 5	; Oscillator Calibration Value Bit5
.equ	CAL6	= 6	; Oscillator Calibration Value Bit6
.equ	CAL7	= 7	; Oscillator Calibration Value Bit7

; CLKPR - Clock Prescale Register
.equ	CLKPS0	= 0	; Clock Prescaler Select Bit 0
.equ	CLKPS1	= 1	; Clock Prescaler Select Bit 1
.equ	CLKPS2	= 2	; Clock Prescaler Select Bit 2
.equ	CLKPS3	= 3	; Clock Prescaler Select Bit 3
.equ	CLKPCE	= 7	; Clock Prescaler Change Enable


; ***** FUSES ************************************************************
; LOW fuse bits
.equ	CKSEL0	= 0	; Select Clock Source
.equ	CKSEL1	= 1	; Select Clock Source
.equ	CKSEL2	= 2	; Select Clock Source
.equ	CKSEL3	= 3	; Select Clock Source
.equ	SUT0	= 4	; Select start-up time
.equ	SUT1	= 5	; Select start-up time
.equ	CKOUT	= 6	; Clock output
.equ	CKDIV8	= 7	; Divide clock by 8

; HIGH fuse bits
.equ	BOOTRST	= 0	; Select reset vector
.equ	BOOTSZ0	= 1	; Select boot size
.equ	BOOTSZ1	= 2	; Select boot size
.equ	EESAVE	= 3	; EEPROM memory is preserved through chip erase
.equ	WDTON	= 4	; Watchdog Timer Always On
.equ	SPIEN	= 5	; Enable Serial programming and Data Downloading
.equ	DWEN	= 6	; debugWIRE Enable
.equ	RSTDISBL	= 7	; External reset disable

; EXTENDED fuse bits
.equ	BODLEVEL0	= 0	; Brown-out Detector trigger level
.equ	BODLEVEL1	= 1	; Brown-out Detector trigger level
.equ	BODLEVEL2	= 2	; Brown-out Detector trigger level

 

I've tried searching online tutorials on changing the fuses or some example code on doing this in assembly code but can't find anything helpful. It's so frustrating reading a technical document as a newbie or tutorial for the first time. I'm come across two websites that should be helpful but like I just said i'm having a terrible time understanding how to proceed. First website (http://www.engbedded.com/fusecalc) from what i'm gathering is asking the user to input what their wanting to set the clock to then outputs various settings that would need to be implented somewhere in code or through some GUI tool ?! I ASSUME !?. I cannot find any tool in Atmel Studio 6.2 or example code on how to set these fuses. I did a search and found the following website (http://www.atmel.com/webdoc/atmelstudio/atmelstudio.programmingdialog.fuses.html) but I do not see this option when i open up project properties (see attachment "MyOptions"). 

 

Can someone get me started here or at least point me to some tutorials I have not read. At the very least I would like to verify/test what I currently have and what my fuses are set too. Maybe knowing that I can at least work backwards and figure out how to set the appropriate fuses. I hear setting these fuses is like walking on the edge of a knife and those that attempt it without understanding of whats going can really mess up their board. 

 

 

 

 

Attachment(s): 

This topic has a solution.

~regnar86

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

From reading section 9.2 in the 328P datasheet under Table 9-1(Device Clocking Options Select) I assume that the External Clock is being used. I don't understand when it defines a column as CKSEL3...0 and for external clock it says 0000 is the value set for CKSEL3...0. That confuses me.

See this part of the datasheet.  Note especially that a "1" is "unprogrammed" (or "erased"), and a 0 value is "programmed" (or "enabled" or "made").

 

 28.2 Fuse Bits
The ATmega48A/PA/88A/PA/168A/PA/328/P has three Fuse bytes. Table 28-4 - Table 28-9 on page 283
describe briefly the functionality of all the fuses and how they are mapped into the Fuse bytes. Note that the
fuses are read as logical zero, “0”, if they are programmed.

 

 1.) How to change the fuses to select different clock frequencies by Atmel Studio 6.2 tools or by direct assembly coding

I'm not aware of any AVR8 model where you can change fuse settings with code running on that AVR.

 

Note that the fuse selections are for appropriate clock >>source<<.  That is not directly related to clock >>frequency<<.  For example, one could have a 7.37, 8.00, 12, 11.092, 16 MHz crystals, different frequencies, and they would all use the same fuse value for selection of clock source.

 

While running, a useful method of changing speed is via the CLKPR clock-prescaler.  That divides the main clock source, as shown in the related tables.  See also the diagram on

Figure 9-1. Clock Distribution
 

Now, if you set the fuses to use internal oscillator, then besides the CLKPR prescaler you can "tune" the frequency with OSCCAL.

 

Fuses are generally changed with the ISP system.  I have no idea how they are changed in the Arduino environment.

 

I cannot quite tell what the end goal of your mission is.  In my apps, the clock speed [almost] always stays fixed from startup and forever.  In some battery-powered apps, it may be advantageous to slow down at certain times w.r.t. some sleep modes.  Just use CLKPR for that.

 

Remember that when you tweak AVR8's clock speed "on the fly", it may have side effects on operation of the app.  For example, delay loops will be clock-speed-sensitive.  On a more pertinent note, it will affect the speed of peripheral subsystems such as USART, SPI, and TWI.  And of course timers.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

N.B. -- you see the bit definitions for fuse bits and similar in the chip-include file because you can >>read<< them from the AVR...

 

26.2.2 Reading the Fuse and Lock Bits from Software
It is possible to read both the Fuse and Lock bits from software. ...

 

Another note:  Many people here reference the "fuse calculator" at http://www.engbedded.com/fusecalc/

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I cannot find any tool in Atmel Studio 6.2...

Now, is there a particular language?  Particular toolchain?  "Studio" technically is neither, but does have Atmel assembler and GCC tools integrated.  Anyway, if using GCC there are read macros already developed:

http://www.atmel.com/webdoc/AVRL...

 

Macro boot_spm_busy_wait

Macro GET_LOW_FUSE_BITS

Macro GET_LOCK_BITS

Macro GET_EXTENDED_FUSE_BITS

Macro GET_HIGH_FUSE_BITS

Macro boot_lock_fuse_bits_get

Macro boot_signature_byte_get

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I apprciate you putting in the macros but i'm trying to do it in assembly. I'm not understanding a few things that happen after I program my chip and start the debug section. I'm reading the Fuse Low Byte.

 

The instructions from the datasheet say the following...

To read the Fuse Low byte, load the Z-pointer with 0x0000 and set the BLBSET and SPMEN bits in SPMCSR.
When an LPM instruction is executed within three cycles after the BLBSET and SPMEN bits are set in the
SPMCSR, the value of the Fuse Low byte (FLB) will be loaded in the destination register.

 

LDS		R16, SPMCSR //need to set the appropriate bits 
LDI		R16, 0b00001001 //set BLBSET and SPMEN bits (probably could of used ORI)
STS		SPMCSR, R16 //Load new value into SPMCSR register
LDI		ZH, HIGH(0x0000) //Need to load address of Fuse Low Byte
LDI		ZL, LOW(0x0000)
LPM		R17, Z //Load Z into R17 to read/verify

When I start my debug session and start stepping everything is fine until line 3. When I view the I/O registers and step through line 3 it doesn't store 0b00001001 into the SPMCSR register. When I continue line 4,5 and 6 execute fine. I don't know if the value though that is read from R17 is the correct Fuse Low Byte since line 3 failed to load the value 0b00001001 which was suppose to set the SPMCSR register correctly as the datasheet indicated. The R17 value is 0x08.

 

Can you suggest what is causing SPMCSR not to load?

 

 

~regnar86

Last Edited: Wed. Jan 21, 2015 - 01:20 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I switched up some some instructions and did the following. I thought maybe I need to use the ORI instruction and then use OUT instead of STS. Still not for sure why I can't use STS. But this way does set the SPMCSR register and during my debug session from my board I get the following output for the Fuse Low Byte 

 

LDI		ZH, HIGH(0x0000)
LDI		ZL, LOW(0x0000)
LDS		R16, SPMCSR
ORI		R16, 0x09
OUT		SPMCSR, R16
LPM		R0, Z

R0 (Fuse Low Byte) reads 0xE0

 

Is that a typical setting for Fuse Low Byte?

 

~regnar86

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How to change the fuses to select different clock frequencies by Atmel Studio 6.2 tools or by direct assembly coding

I'm not an expert when it comes to Fuses, but I'll share a thought or two:

 

For many designers, it is sufficient to set the Fuses as one desires when the uC is connected to a Programmer and to Studio 6.whatever.

 

One generally sets the clock source they will be using, (very carefully until you know what you are doing), and sets the Watchdog timer, Brownout Detector, etc., if desired.

For playing around you don't need either the Watchdog timer or the Brownout Detector.

 

The key point to keep in mind is that it is easy to mis-set the uC's clock source to expect an external oscillator.

An external oscillator is a small dip package with its own V+ and Ground, that outputs a square wave signal, that is fed into one of the Xtal pins on the uC.

One usually means to select an external crystal, which is a two lead device that uses the osc circuit inside the uC to form an oscillator and generate the desired clock frequency.

If you stick with the internal RC oscillator you can't get into too much trouble, but eventually you have to take the plunge and start experimenting with the other settings.

 

I'm not familiar with "setting Fuses" using assembler.

Note that it is easy to read the Fuses when the uC is connected to a Programmer and to Studio.

Just don't hit the Write button unless you really mean it.

 

JC

 

  

Last Edited: Wed. Jan 21, 2015 - 02:50 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Generally it's not a good idea to mess with the fuses unless your target board isn't working.  You can try numerous settings and they won't seem to do anything until you try one setting that causes to board to stop working.  The fuses that truly mess up the AVR are in the high fuse byte.  Don't mess around with SPIen, ResetEnable, or DWenable fuses.  You'll need a Hi-Voltage Programmer like a Dragon to restore your XPlain. Since this XPlain is still working, I wouldn't mess with the fuses at all.  If you have an oscilloscope, then you might try activating (setting to logic 0) the clock-out fuse.  Then you can look with a scope and see that signal on one of the pins (not sure which).  The only fuse that I ever change is to deactivate (set to logic 1) the Clock-divide-by-8 fuse.  I use the internal 8MHz system clock with the longest reset period.

 

The LDS instruction is used instead of IN with peripheral registers over 0x3f.  It is used with STS instead of OUT.  IN and OUT are used for registers 00-0x3f. This is a legacy from the early AVR models that had all peripheral regs 0x3f or less. Since the board is still working, the use of STS with OUT SPMCSR, r16 hasn't screwed anything up (yet).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1.) How to change the fuses to select different clock frequencies by Atmel Studio 6.2 tools or by direct assembly coding

Mega328 on your Xplained board is externaly clocked at 16 MHz.

The low fuse in m328 is accordingly set to

SUT_CKSEL = EXTCLK_6CK_14CK_65MS

as shown in Xplained manual.

Changing the fuses is a nonsens here. Fuses cannot be set to another clock source.

 

The only way to change the clock frequency is to divide this 16 MHz by 2, 4, 8 etc. using CLKPR register.

In the code you can use

// divide clock by 2
LDI R16, 0x80
STS CLKPR, R16
LDI R16, 1
STS CLKPR, R16

// divide clock by 4
LDI R16, 0x80
STS CLKPR, R16
LDI R16, 2
STS CLKPR, R16

// see CLKPR description in datasheet

 

 

 

 

Last Edited: Wed. Jan 21, 2015 - 05:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just to note that if you use avr-as rather than Atmel Asm2 as your assembler in Studio you can benefit from:

 

http://www.nongnu.org/avr-libc/u...

http://www.nongnu.org/avr-libc/u...

 

But note that all this really does is embed a .fuse (and possibly .lock) section within the final ELF file. You can then ask the ISP driving software in Studio to program it all in one go and it will not only program flash (as normal) but also set the fuse and lock bits too - all in one go.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As a programmer & hardware designer, I concentrate on the what the program needs to do, finish that first, then set the fuses as needed, if they need changed at all.   Never have I needed to look at or set fuses in one of my programs.  I have even ignored the "clock / 8" fuse setting in some programs as I can change the clock using the CLKPR reg in my initial setup code. 

 

Jim

 

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm having some trouble reading the fuse high byte from my Xplained Mini. Below is a detailed description of what is going on.

 

THE INSTRUCTIONS I FOLLOWED WHEN READING THE FUSES:

 

I followed the instructions in the datasheet on page 257 section 26.2.2. I'm including a screenshot of that for your convenience (See attachment "SettingFuses"). 

 

WHAT IS GOING ON:

 

My code which can be viewed below reads the fuse high and fuse low byte. Before I program my board I run through my program line by line using the simulator. Every line of instruction steps through correctly as I verified each instruction through using the I/O view and Register View. I'm going to describe what I'm doing in steps next so you can better understand what i'm doing.

 

1.) Before I upload "program" any code to my board I set the debug interface to debugWire and go into "Device Programming" look under the "Fuse" tab and verify the values for the low and high byte. These values are High = 0xDF and Low = 0xE0. So you can see what i'm talking about I've included a screenshot of that window (See Attachment "DeviceProgWindow_Fuses"). This is ALL I DO under the tab "Fuses". I don't click on anything or change anything. 

 

2.) After verifying the above I click on the tab "Memories" and click "Program". The code uploads successfully as it indicates.

 

3.) I start a debug session and a dialog box comes up wanting me to set the DWEN fuse. I just click "Ok" and continue on into the debugging stage.

 

4.) When debugging in real time I start by executing line by line stepping through each instruction using the F11 key. I do this several times over and over making sure the values that are read are consistent each time. The values for the fuse low and fuse high byte are as follows...

F_HIGHBYTE = R17 = 0x9F

F_LOWBYTE = R18 = 0xE0

 

Notice that the F_HIGHBYTE is different than the value that was in the "Device Programming" window in step 1.

 

WHAT I EXPECTED THE VALUES TO BE AND HOW I TROUBLESHOOTED:

 

I consulted the datasheet several times to verify what the DEFAULT values are. This information can be found in the datasheet on page 283-284 section 28.2. I'm attaching a screenshot of that for your convenience (See attachment "DefaultFuseSettings"). Other than a few changes everything should be set to those default values "for example the target uses an external clock so that is one setting that will be different in fuse low byte".

 

During the real time debugging session I thought maybe my ZH and ZL registers were not loading the correct memory address. However, after stepping through those instructions several times I didn't notice any errors. They were executing correctly in other words. 

 

Next I thought that I would just execute the whole program during the real time debugging session by clicking on the green arrow. This didn't change anything. It was still persistent in reading the same values.

 

I tried uploading my code a second and a third time running through the same procedures during debug session. Nothing changed. It was still persistent.

 

MY QUESTIONS:

 

1.) Why isn't the fuse high byte reading what it was under the "Fuses" tab in "Device Programming"

 

2.) What steps can I take to correct this via code or through troubleshooting methods I have not tried yet?

 

3.) Also if you have any suggestions on how to improve the efficiency of this code or simplify it please feel free to comment.

 

MY CODE:

 

/*--------------------------------------PROJECT_TITLE------------------------------------
File:						Read_FuseHighByte.asm
Date:						1/22/2015 12:00:04 PM
Author:						ErEbUs
SoftwareIDE:				Atmel Studio 6.2
Hardware:					ATmega328P Xplained Mini
Debugger/Programmer:		Embedded Debugger mEBDG/ATmega32U4
Target:						ATmega328P
Summary:					Read the Fuse High & Low Byte
----------------------------------------PROJECT_TITLE----------------------------------*/

/*--------------------------------------NOTES--------------------------------------------
(See I/O Memory 8.5 in DATASHEET)
When addressing I/O Registers as data space using LD and ST instructions 0x20 must be
added to the address of the I/O Registers used. These I/O registers are the ones
that fall within the following range (see Register Summary)...
0x00(0x20) --> 0x3F(0x5F)
EX: In the include file "M328PDEF.INC" address of SPMCSR is at address (0x37). We add the
value 0x20 to 0x37 IF AND ONLY IF WE ARE USING THE LD AND ST (LDI,STS) INSTRUCTIONS.
----------------------------------------NOTES------------------------------------------*/

/*--------------------------------------HARDWARE_MAP------------------------------------
----------------------------------------HARDWARE_MAP-----------------------------------*/

/*--------------------------------------MEMORY_MAP---------------------------------------
EEPROM Data Memory [1Kbytes] 
In-System Reprogrammable Flash Program Memory [32Kbytes] [16Kbytes x 16bits] [2 Sections]
 _______________________________________
|           Application Flash           | 0x0000
|                                       |
|                                       |
|                                       |
|                                       |
|_______________________________________|
|               Boot Flash              |
|                                       |
|                                       | 
|                                       |
|                                       |
|_______________________________________| 0x3FFF
SRAM Data Memory [2Kbytes] [2303 locations]
 _______________________________________
|           Register File [32]          | 0x0000
|                                       |
|                                       |
|                                       |
|_______________________________________| 0x001F
|      Standard I/O Registers [64]      | 0x0020
|                                       |
|                                       |
|[0][0][0][0][BLBSET=1][0][0][SPMEN= 1] | 0x0037(0x57)SPMCSR //Set in order to read
|                                       |
|                                       |
|_______________________________________| 0x005F
|      Extended I/O Registers [160]     | 0x0060
|                                       |
|                                       | 
|                                       |
|                                       |
|                                       |
|                                       |
|_______________________________________| 0x00FF
|     Internal Data SRAM [2048 x 8]     | 0x0100
|                                       |
|                                       |
|                                       | 
|                                       |
|                                       |
|                                       | 
|                                       |
|                                       |
|_______________________________________| 0x08FF
----------------------------------------MEMORY_MAP-------------------------------------*/

//--------------------------------------CODE_START---------------------------------------
.NOLIST								//reduce .lss file
.INCLUDE "M328PDEF.INC"						//include device file
.LIST
.DEF F_HIGHBYTE = R17
.DEF F_LOWBYTE = R18
.CSEG							        //start of flash program memory
.ORG 0x0000
		RJMP	MAIN					//reset vector
MAIN:	        LDI		R16, HIGH(RAMEND)		//initialize stack
		OUT		SPH, R16
		LDI		R16, LOW(RAMEND)
		OUT		SPL, R16

		LDI		ZH, HIGH(0x0003)		//reading fuse high byte
		LDI		ZL, LOW(0x0003)
		LDI		R16, 0x0009			//set blbset and spmen in spmcsr
		STS		0x0057, R16			//store in spmcsr + 0x0020 (see notes)
		LPM		F_HIGHBYTE, Z			//store fuse high byte in r17

		CLR		R30
		CLR		R31

		LDI		ZH, HIGH(0x0000)		//reading fuse low byte
		LDI		ZL, LOW(0x0000)
		LDI		R16, 0x0009
		STS		0x0057, R16
		LPM		F_LOWBYTE, Z
//--------------------------------------CODE_END-----------------------------------------

//--------------------------------------SUBROUTINE_START---------------------------------
//--------------------------------------SUBROUTINE_END-----------------------------------



 

Attachment(s): 

~regnar86

Last Edited: Thu. Jan 22, 2015 - 11:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm an idiot. Apologies for wasting anybody's time. I believe I'm misunderstanding a simple rule...

 

The values listed for fuse high and fuse low byte in the "Device Programming" window under the tab "Fuses" will only get programmed into the target if and only if I click the button "Program". I was guessing that since I hit the "Program" button under the tab "Memories" in the "Device Programming" window it would include setting the fuses as well. I'm assuming this is not so.

 

Furthermore, by looking at the fuse high byte value read into R17, I believe this values is correct. 0x9F = 0b10011111 would mean DWEN and SPIEN are programmed which makes since.

 

Am I correct or not? 

 

~regnar86

Last Edited: Thu. Jan 22, 2015 - 11:51 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are correct.

The Memory Program button will not program the Fuses.

 

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And you changed the fuses when you enabled debug wire! 

 

 

Jim

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...