Have basic Low Speed SWIM read on the fly working.

Only reads one byte, but good enough.. to get things done.

Code should actually work for low and high speed, but have only tested
high speed on writes so far.

Having issue where reads can fail at times.  Esp with long strings of
'0'..  Perhaps operating at high speed would improve matters..
Although I'm also realizing maybe I'm not waiting for the device to reset
and reload HSI trim factory value, need to check that..

The new assembly file/function does everything needed so can start cutting
out inline assembly from swim_out function.

Swim code needs to run at 48Mhz.  Realizing this is pretty vital to having
enough time to handle high speed.  And timing of artificial pull-up
requires high trimmability..
This commit is contained in:
Paul Molloy 2017-09-12 22:36:25 -05:00
parent 0e0e307f64
commit 49b4639aa4
9 changed files with 636 additions and 13 deletions

View File

@ -65,6 +65,8 @@ CFLAGS+= $(DEFINE) $(INCLUDE)
SOURCES=$(wildcard source/*.c source_stm_only/*.c)
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
ASM_SRC=$(wildcard source/asm_stm/*.s)
#all: dir shared $(BUILD)/$(PROJ).axf $(BUILD)/$(PROJ).elf $(BUILD)/$(PROJ).hex $(BUILD)/$(PROJ).bin size
all: dir shared $(BUILD)/$(PROJ).elf $(BUILD)/$(PROJ).hex $(BUILD)/$(PROJ).bin size
@ -72,10 +74,10 @@ all: dir shared $(BUILD)/$(PROJ).elf $(BUILD)/$(PROJ).hex $(BUILD)/$(PROJ).bin s
# $@ is shortcut for the target, $^ is shortcut for prereqs
# TARGET: PREREQS
$(BUILD)/$(PROJ).axf: $(STARTUP) $(OBJECTS)
$(CC) $^ $(CFLAGS) $(LFLAGS) -o $@
$(CC) $^ $(ASM_SRC) $(CFLAGS) $(LFLAGS) -o $@
$(BUILD)/$(PROJ).elf: $(STARTUP) $(OBJECTS)
$(CC) $^ $(CFLAGS) $(LFLAGS) -o $@
$(CC) $^ $(ASM_SRC) $(CFLAGS) $(LFLAGS) -o $@
$(BUILD)/$(PROJ).hex: $(BUILD)/$(PROJ).elf
$(OBJCOPY) -O ihex $^ $@

View File

@ -23,6 +23,7 @@ BASE=.
# Compiler & Linker
CC=arm-none-eabi-gcc
ASM=arm-none-eabi-as
CXX=arm-none-eabi-g++
OBJCOPY=arm-none-eabi-objcopy
SIZE=arm-none-eabi-size
@ -31,7 +32,7 @@ SIZE=arm-none-eabi-size
ARCH_FLAGS=-mthumb -mcpu=cortex-m$(CORTEX_M)
# Startup code
STARTUP=$(BASE)/include_stm/startup_ARM$(CORE).S
STARTUP=$(BASE)/include_stm/startup_ARM$(CORE).S
# -Os -flto -ffunction-sections -fdata-sections to compile for code size
CFLAGS=$(ARCH_FLAGS) $(STARTUP_DEFS) -Os -flto -ffunction-sections -fdata-sections -g
@ -61,21 +62,23 @@ DEFINE+=\
INCLUDE=-I ./include_stm
CFLAGS+= $(DEFINE) $(INCLUDE)
#SOURCES=$(wildcard source/**/*.c source/*.c)
SOURCES=$(wildcard source/*.c source_stm_only/*.c)
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
ASM_SRC=$(wildcard source/asm_stm/*.s)
#all: dir shared $(BUILD)/$(PROJ).axf $(BUILD)/$(PROJ).elf $(BUILD)/$(PROJ).hex $(BUILD)/$(PROJ).bin size
all: dir shared $(BUILD)/$(PROJ).elf $(BUILD)/$(PROJ).hex $(BUILD)/$(PROJ).bin size
#build axf file output (basically elf with DWARF debug info)
# $@ is shortcut for the target, $^ is shortcut for prereqs
# TARGET: PREREQS
$(BUILD)/$(PROJ).axf: $(STARTUP) $(OBJECTS)
$(CC) $^ $(CFLAGS) $(LFLAGS) -o $@
$(CC) $^ $(ASM_SRC) $(CFLAGS) $(LFLAGS) -o $@
$(BUILD)/$(PROJ).elf: $(STARTUP) $(OBJECTS)
$(CC) $^ $(CFLAGS) $(LFLAGS) -o $@
$(CC) $^ $(ASM_SRC) $(CFLAGS) $(LFLAGS) -o $@
$(BUILD)/$(PROJ).hex: $(BUILD)/$(PROJ).elf
$(OBJCOPY) -O ihex $^ $@

View File

@ -0,0 +1,514 @@
//;Ensure that your assembly code complies with the Procedure Call Standard for the ARM Architecture (AAPCS).
//;
//;The AAPCS describes a contract between caller functions and callee functions. For example, for integer or pointer types, it specifies that:
//;
//; Registers R0-R3 pass argument values to the callee function, with subsequent arguments passed on the stack.
//; Register R0 passes the result value back to the caller function.
//; Caller functions must preserve R0-R3 and R12, because these registers are allowed to be corrupted by the callee function.
//; Callee functions must preserve R4-R11 and LR, because these registers are not allowed to be corrupted by the callee function.
//;
//;For more information, see the Procedure Call Standard for the ARM Architecture (AAPCS).
//;WARNING!!! logic instructions all affect flags despite the 's' postfix arm_none_eabi_gcc doesn't like 's' instructions
//; but the 's' affect flag instructions are the only ones the M0 supports
//; because of this, issue the following code isn't compatible with other cores.
.equ BSSR, 0x18
.equ BRR, 0x28
.equ OTYPER, 0x04
.equ IDR, 0x10
.equ NO_RESP, 0xFF
.equ ACK, 0x01
.equ NAK, 0x00
.equ HERR, 0x0E
.equ PERR, 0x09
.macro swim_lo
strh swim_mask, [swim_base, #BRR]
.endm
.macro swim_hi
strh swim_mask, [swim_base, #BSSR]
.endm
.macro swim_pp
strh pushpull, [swim_base, #OTYPER]
.endm
.macro swim_od
strh opendrain, [swim_base, #OTYPER]
.endm
.equ SWIM_RD, 0x01
.equ SWIM_WR, 0x02
.equ SWIM_HS_BIT, 4
.equ SWIM_HS_MSK, 0x10
.equ HS_DELAY, 4
.equ LS_DELAY, 22
.globl swim_xfr
.p2align 2
.type swim_xfr,%function
//;r0 - r3 contain function args (excess on stack)
//;swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
//;spddir_len = (SWIM_RD_LS<<16) | len;
//; stream .req a1 this arg is moved to variable reg after stack push
stream_arg .req a1
rv .req r0
len .req a2
swim_base .req a3
swim_mask .req a4
swim_xfr: //;Function entry point.
.fnstart
//;need a few extra variable registers, but they need to be preserved
pushpull .req v1
opendrain .req v2
stream .req v3
speed .req v4
//;high registers r8-r12 are very limited following instructions can utilize them
//; ADD, CMP, LDR PC-rel, BX, BLX, MSR, MSR
//; Docs list that MOV can only use R0-7, but testing and compilation proves otherwise
//; Additionally, arm_none_eabi_gcc uses MOV R8, R8 as it's NOP!!
rdwr .req v5
push {pushpull, opendrain, stream, speed, lr}
mov speed, rdwr //;preserve r8 high register can't pop/push
push {speed}
//; move stream arg out of r0, and into variable register so r0 is free
mov stream, stream_arg
//; len contains speed and direction data, must trim off and move
//; into variable registers
//;spddir_len = (SWIM_RD/WR_LS/HS<<16) | len;
mov r0, len
lsr r0, #16
cmp r0, #SWIM_HS_MSK
bpl high_speed
mov speed, #LS_DELAY
b speed_dir
high_speed:
mov speed, #HS_DELAY
speed_dir:
//;mask out speed bit and store in rdwr
//;shift speed bit left past carry
lsl r0, #(16-SWIM_HS_BIT + 16) //;16-BIT shifts bit to b16, 16 shifts to carry = 28
lsr r0, #(16-SWIM_HS_BIT + 16) //;carry doesn't shift in
mov rdwr, r0
//; mask out upper bits of len
mov r0, #0xFF
and len, r0
//; ~83nsec per unit of delay change
//;mov speed, #22 //;22 = 2.75usec bit time delay variable
//;mov speed, #4 //;4 = 1.25usec bit time delay variable
//;mov speed, #22
//; set pushpull and opendrain to values we can write to otyper register
//; to quickly change direction of the SWIM pin only
ldr pushpull, [swim_base, #OTYPER]
mov opendrain, pushpull
//; variables hold current OTYPER register value
//; set bit for opendrain, clear for pushpull
orr opendrain, swim_mask
bic pushpull, swim_mask
//; now these registers can be written directly to otyper GPIO reg
//; to quickly change SWIM pin direction and not affect other pins
//;set flags so first bit is header '0' "from host"
//;the stream comes in as 16bit value with stream bit 7 in bit position 15
//;shift the stream left so the current transfer bit is in bit position 31
//;15 -> 30 is 15bit shifts, this leaves header zero in bit position 31
//;store stream in r4
lsl stream, #15
bit_start:
//;always start going low
swim_lo
//;current bit is stored in bit31 and Negative flag is set if
//;current bit is '1'
bpl cur_bit_zero
//;delay to extend low time for '1'
nop
nop
nop
nop
nop
nop
nop
//;go high since current bit is '1'
swim_pp
swim_hi
swim_od
b det_next_bit
cur_bit_zero:
//;must delay same amount of time as instructions above since branch
//;add delay here to make '0' longer until equal to '1'
mov r0, #1
bl delay_r0
det_next_bit:
//;determine if this is the last bit
sub len, #1
//;if last bit, go to stream end to prepare for ACK/NAK latch
bmi out_end
//;delay until 'go high' time for '0'
//;add delay here to make all bit transfers longer
//;20-> 2.56usec bit time
//;21-> 2.65usec
//;22-> 2.73usec
mov r0, speed ;//4-HS 22-LS
bl delay_r0
nop //;22+nop = 2.75usec = low speed timing perfect!
//; high speed bit time has same 0-high, 1-lo time
//; only difference is bit time is 1.25usec
//;Negative flag is now set for '1', and clear for '0'
//;always go high for '0' (no effect if already high for '1')
swim_pp
swim_hi
swim_od
//;delay to extend high time of '0'
nop
nop
//;determine next bit value
lsl stream, #1
//;go to bit start
b bit_start
out_end:
//;delay until 'go high' time for '0'
mov r0, speed
sub r0, #1 ;//this decrement keeps both HS and LS perfectly aligned
bl delay_r0
//;always go high for '0' (no effect if already high for '1')
swim_pp
swim_hi
swim_od
//;delay until time to latch ACK/NAK from device
mov r0, #4 //;1-2:NR 3: usually RESP, not always/5-varies RESP/NO RESP
//; sometime the device takes longer...
//; 3 was failing for some, inc to 5
//; 5 works, '1' NAK has low pulse width of 500-600nsec, trying 4
//; 4 seems stable. low pulse time is 400-550nsec
bl delay_r0
//;first need to ensure device is actually responding
//;sample when output should be low for a 1 or 0
//;appears the device inserts a little delay ~220nsec between final host bit
//;and ACK/NAK
//;total time between host high (parity bit = '0')
//;and device ACK/NAK low is ~450nsec
//;debug toggle pushpull below
//;measurements showed pulse ~100nsec after device took SWIM low with 3 above
//;swim_pp
//;swim_od
//;latch SWIM pin value from GPIO IDR
ldrh rv, [swim_base, #IDR]
and rv, swim_mask
//;if it wasn't low, then the device didn't respond, so return error designating that
//;__asm volatile ("bne no_response\n\t");
beq wait_ack_nak
//;return 0xFF
mov rv, #NO_RESP
b exit_swim
wait_ack_nak:
//;don't have a strong enough pull-up resistor on SWIM pin
//;to compensate for this we can cheat by quickly toggling
//;to push-pull after device should have gone high for ACK = '0'
//;this does create bus contension for breif period but don't have much choice here..
//;only other alternative is to install pullup on board/programmer
//;swim_pp no delay_r0 outputs pulse ~240nsec after device goes low with 3 above
//;swim_od
//; 3 above, and 2 here equates to pulse high 640nsec after device goes low
//; 3 above, and 1 here equates to pulse high 460nsec after device goes low
//; 3 above wasn't stable, incremented to 4 and works, give 400-550nsec pulse low
//; mov r0, #1
//; bl delay_r0
;//r0=1: for ACK, artf pullup enabled 150-300nsec after device stops driving low
;//this is okay timing allowance as being early would cause misread
;//could possibly tighten with nops instead..
nop
nop
nop
nop //;4 nops = 250-350nsec low pulse width for ACK '1'
nop
nop //;5 nops = 300-450nsec low pulse width
swim_pp
swim_od
//;now we can sample for NAK/ACK as artifical pullup has been inserted above
//;if device output ACK, the artificial pullup doesn't cause contension
//;but if device output NAK "0" device should still be driving low
//;latch SWIM pin value from GPIO IDR
ldrh rv, [swim_base, #IDR]
and rv, swim_mask
//; NAK: rv=0, ACK: rv=swim_mask
beq return_nak
mov rv, #ACK
//; device sent ACK, if this is a read operation
//; need to capture data sent by the device
mov stream, #SWIM_WR
cmp rdwr, stream
beq exit_swim
//; Sent the last byte of the command successfully
//; Now read in data from device
//; A bit of a challenge because of lacking legit pullup
//; setup for read transfer
mov len, #9 //;read 9bits total, then output ACK
//; poll until device takes SWIM low for header bit
//; perhaps setting an interrupt and waiting for it would be better
//; due to less jitter from polling..
poll_header:
ldrh stream, [swim_base, #IDR]
and stream, swim_mask
bne poll_header
//;device took SWIM low
//;pulse for artifical pullup
mov r0, #1 //;1: 350-450nsec equates to 100-200nsec delay ~okay
bl delay_r0
//;nop
//;nop
//;nop //; 3xnop = 250-300nsec low pulse for '1' header from device
//;nop //; 4xnop = 250-350nsec
//;nop //; 5xnop = 250-300 never seems to change!!!!
//; the device seems to stall for a little bit due to the delayed pull-up
//; the bit time for the header seems to extend to ~3usec
//; but perhaps we can take advantage of this to better align with the device
//; add delay between here and read_next_bit to lengthen header bit
//; seemed to be a little early at times..
swim_pp
swim_od
b read_next_bit
.p2align 4
read_next_bit:
swim_pp
swim_od
//; header bit '1' is now high
//; give a little delay between push pulse and reading
//; this instruction can be performed out of order
//; this didn't end up being a real problem, but it can't hurt
lsl stream, #1
//; read bit, should be '1' for header on first read
//; sample and place value in carry, then rotate in
ldrh r0, [swim_base, #IDR]
and r0, swim_mask
//; Z flag contains inverse of bit
mrs r0, APSR
//; bit 30 of r0 contains inverse of bit
//; shift left to mask away any upper bits
lsl r0, #1
//; shift right to mask away lower bits
lsr r0, #31
//; shift stream and or in r0 (stream does have mask bit set from poll loop)
//; moved up to provide delay between push and read
//;lsl stream, #1
orr stream, r0
//; now stream holds the inverse stream (plus mask junk on upper half)
//; wait bit time, enable artifical pullup, and sample
mov r0, speed
sub r0, #2 //; need to save some delay for after pushing '0' high
bl delay_r0
//; push high for logic '0'
//;swim_pp
//;swim_od
//;mov r0, #2
//;bl delay_r0
//; above isn't always getting SWIM pin high for '0'
//; can only assume that it's too early
swim_pp
swim_od
mov r0, #2
bl delay_r0
//; seems to drop out at times..
//; adding a check here to verify that SWIM is high looks like it would
//; catch when the device drops out
//; check if last bit in read
sub len, #1
//;if last bit, go to stream end to prepare for ACK/NAK latch
bpl read_next_bit
//; last bit calc and send parity, or just always send ACK
//; could send back to poll header but not sure it's worth retrying..
//; not sure a failure would even allow us to properly send a NAK
always_send_ack:
//; ACK is a '1' from host, so need a short pulse low
//; this is actually a little late, but seems the device sends it a little late as well
//; so this happens to align pretty well with the device's timing
swim_lo
swim_pp
mov r0, #1
bl delay_r0
swim_hi
swim_od
//; organize return data
//; MSB NAK/NORESP from last write
//; if ACK, then return read result
//; TIMEOUT, HEADER error, PAIRITY error
//; ACK entire transfer good!
//; LSB data read back
//; stream data sturcture
//; upper bits may contain swim_mask value
//; all values inverted:
//; b9 header '1' -> '0'
//; b8-1 data inverted 1's compliment
//; b0 pairity inverted
//; write corrupted data for testing
//; inverted 1 header bit - F0 data - 0 pairitybit
//; 0 0F 1
//; mov stream, #0x1F ;// good data should report 0xF0 - ACK
//; mov stream, #0x1E ;// toggle pairity data should report PAIRITY ERROR
;// bad header data
//; mov stream, #0x80
//; mov rv, #2
//; lsl stream, rv
//; mov rv, #1 ;// set correct pairity
//; orr stream, rv
//; store result as-is
mov rv, stream
//; check that header was read as '1' (from device) and stored as '0'
mov len, #0x80 ;// bad header data would have bit 9 set ('1' device header is inverted)
mov swim_mask, #2
lsl len, swim_mask ;// shift bit 7 into bit 9
and stream, len
//; should be zero if header stored as '0'
bne header_error
//; calc pairity
//; must add to registers to add with carry
//; swim_mask no longer needed
mov swim_mask, #0
//; store stream temporarily in len reg while shifting pairity bit to carry
lsr len, rv, #1
//; stream should be zero on entry
//; add inverted pairity bit
adc stream, swim_mask
lsr len, #1
//; add bit0-3
adc stream, swim_mask
lsr len, #1
adc stream, swim_mask
lsr len, #1
adc stream, swim_mask
lsr len, #1
adc stream, swim_mask
lsr len, #1
//; add bit4-7
adc stream, swim_mask
lsr len, #1
adc stream, swim_mask
lsr len, #1
adc stream, swim_mask
lsr len, #1
adc stream, swim_mask
//; individual sumation of all bits should be even when pairity included
//; but for inverted data, the sum should be odd
//; shift sum lsbit into carry and verify it's set (equates to odd)
lsr stream, #1
bcc pairity_error
//; all is good, just return the inverted data!
lsr rv, #1
//; mask out data alone
mov len, #0xFF
and rv, len
//; invert data to true data
eor rv, len
//; shift to upper byte
lsl rv, #8
//; add in the ACK to lower byte
add rv, #ACK
//; since things are little endian
//; the output is a 16bit int
//; so the value we output will be byte swapped
//; when interpreted as 16bit int
b exit_swim
header_error:
//; header wasn't '1' as expected when reading from device
mov rv, #HERR
b exit_swim
pairity_error:
mov rv, #PERR
b exit_swim
return_nak:
mov rv, #NAK
exit_swim:
//;r0 contains return value on exit (already done prior to this point)
//;r4-r11 & lr must be preserved to entry values
pop {speed}
mov rdwr, speed //;restore r8 high register can't pop/push
pop {pushpull, opendrain, stream, speed, pc}
//; bx lr //;Return by branching to the address in the link register.
.fnend
//;.globl delay_r0
//; ~83nsec per unit of delay change
.p2align 2
.type delay_r0,%function
count .req a1
delay_r0: //;Function entry point.
.fnstart
sub count, #1
bne delay_r0
bx lr
.fnend

View File

@ -22,6 +22,7 @@ uint8_t swim_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *
#define RD_LEN 0
#define RD0 1
#define RD1 2
uint16_t *ret_hword = (uint16_t*) &rdata[1];
#define BYTE_LEN 1
#define HWORD_LEN 2
@ -33,10 +34,13 @@ uint8_t swim_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *
rdata[RD0] = swim_out( 0x0000, 4); break;
case WOTF:
rdata[RD_LEN] = BYTE_LEN;
rdata[RD0] = swim_woft(operand, miscdata); break;
// case ROTF:
// rdata[RD_LEN] = BYTE_LEN;
// rdata[RD0] = swim_roft(); break;
rdata[RD0] = swim_woft( operand, miscdata ); break;
case ROTF:
rdata[RD_LEN] = HWORD_LEN;
//this assignment actually undoes the byte swap
//first index of data includes NAK/ACK just like write routines which only return ACK/NAK
//second index of data includes actual byte read back
*ret_hword = swim_roft( operand ); break;
default:
//opcode doesn't exist
return ERR_UNKN_SWIM_OPCODE;
@ -325,10 +329,84 @@ uint16_t append_pairity(uint8_t n)
}
}
/* Desc:read byte from SWIM
* Pre: swim must be activated
* Post:
* Rtn: should return success/error and value read
*/
//must match swim.s .equ statements!!!
#define SWIM_RD_LS 0x01
#define SWIM_WR_LS 0x02
#define SWIM_RD_HS 0x11
#define SWIM_WR_HS 0x12
uint16_t swim_roft(uint16_t addr)
{
//If >24Mhz SYSCLK, must add wait state to flash
//can also enable prefetch buffer
FLASH->ACR = FLASH_ACR_PRFTBE | 0x0001;
//switch to 48Mhz
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_PLL;
uint16_t data_pb;
uint32_t ack_data;
uint32_t spddir_len;
//bit sequence:
//1bit header "0" Host comm
//3bit command b2-1-0 "001" ROTF
//1bit pairity xor of cmd "1"
//1bit ACK "1" or NAK "0" from device
// 0b0_0011
data_pb = 0x3000;
spddir_len = (SWIM_WR_LS<<16) | 4; //data + pairity ( '0' header not included)
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
if (ack_data != ACK) goto end_swim;
//write N "number of bytes for ROTF"
data_pb = 0x0180;
spddir_len = (SWIM_WR_LS<<16) | 9;
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
if (ack_data != ACK) goto end_swim;
//write @E extended address of write
//always 0x00 since targetting stm8s003 which only has one section
data_pb = 0x0000;
spddir_len = (SWIM_WR_LS<<16) | 9;
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
if (ack_data != ACK) goto end_swim;
//write @H high address of write
data_pb = append_pairity( addr>>8 );
spddir_len = (SWIM_WR_LS<<16) | 9;
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
if (ack_data != ACK) goto end_swim;
//write @L high address of write
data_pb = append_pairity( addr );
//this is a read xfr because device will output data immediately after
//writting last byte of command info
spddir_len = (SWIM_RD_LS<<16) | 9;
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
//read DATA portion of write
//More bytes can be written
//any time NAK is recieved must resend byte
end_swim:
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_HSE;
//Don't need wait states or prefetch buffer anymore
FLASH->ACR = 0x0000;
return ack_data;
}
/* Desc:write byte to SWIM
* Pre: swim must be activated
* Post:
* Rtn: 0-NAK, 1-ACK beware, no response looks like ACK!
* Rtn: 0-NAK, 1-ACK, 0xFF no response
*/
uint8_t swim_woft(uint16_t addr, uint8_t data)
{

View File

@ -13,7 +13,11 @@ uint8_t swim_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *
void swim_activate();
void swim_reset();
uint8_t swim_out(uint16_t stream, uint8_t len);
uint16_t swim_roft(uint16_t addr);
uint8_t swim_woft(uint16_t addr, uint8_t data);
uint16_t append_pairity(uint8_t n);
//assembly functions from swim.s
extern uint32_t swim_xfr( uint16_t data_pb, uint32_t spddir_len, GPIO_TypeDef *swim_base, uint16_t swim_mask);
#endif

View File

@ -122,6 +122,8 @@ void init_clock()
//at startup HSI is selected SW = 00
RCC->CFGR |= RCC_CFGR_SW_HSE;
//TODO poll RCC->CFGR SWS bits to ensure sysclk switched over
//Now the SYSCLK is running directly off the HSE 16Mhz xtal
/* (1) Test if PLL is used as System clock */

View File

@ -405,8 +405,13 @@ local function swim( opcode, operand, misc, data )
end
--process the return data string and return it to calling function
RETURN_ACK_IDX = 3
RETURN_DAT_IDX = 4
if data_len then
return string_to_int( data:sub(RETURN_DATA, data_len+RETURN_DATA), data_len)
--return string_to_int( data:sub(RETURN_DATA, data_len+RETURN_DATA), data_len)
error_code = data:byte(RETURN_ACK_IDX)
data_len = data:byte(RETURN_DAT_IDX)
return error_code, data_len
else
return nil
end

View File

@ -38,11 +38,26 @@ function main ()
dict.io("SWIM_INIT", "SWIM_ON_EXP0")
dict.swim("SWIM_ACTIVATE")
--holds SWIM pin low for 16usec+ to reset SWIM comms incase of error
dict.swim("SWIM_RESET")
--write 0A0h to SWIM_CSR
--bit 5: allows entire memory range to be read & swim reset to be accessed
--bit 7: masks internal reset sources (like WDT..?)
print("wotf SWIM_CSR:", dict.swim("WOTF", 0x7F80, 0xA0))
--read SWIM_CSR
print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
print("rotf SWIM_CSR:", string.format("%X %X", dict.swim("ROTF", 0x7F80)))
dict.swim("SWIM_RESET")
print("wotf SRST:", dict.swim("SWIM_SRST"))
print("wotf SWIM_CSR:", dict.swim("WOTF", 0x7F80, 0xA0))
--now the SRST command is available, whole memory range available, and internal resets disabled
--by default there is now a breakpoint set at reset vector

View File

@ -28,7 +28,7 @@
//SWIM commands
#define SWIM_SRST 2 //reset device RL=3 (error, len, NAK/ACK)
#define ROTF 0x11 //read on the fly only one byte RL=3 (error, len, data)
#define ROTF 0x11 //read on the fly only one byte RL=4 (usberror, len, swimerror, data)
//#define ROTF_8B 0x18 //read on the fly RL=8
//#define ROTF_128B 0x1F //read on the fly RL=128 (current max due to 254B limit)