INL-retro-progdump/firmware/source_stm_only/usbstm.h

312 lines
17 KiB
C
Raw Permalink Blame History

#ifndef _usbstm_h
#define _usbstm_h
//include target chip port definition library files
#include <stm32f0xx.h>
#include "../source/shared_dictionaries.h"
#include "fwupdate.h"
#define USBDRIVER __attribute__ ((section (".usb_driver")))
//let the compiler perform inline optization, it'll keep code smaller
//this code is all exactly where we want it anyway and separate from
//application code, so inlining is not just okay, it's good!
//#define USBDRIVER __attribute__ ((section (".usb_boot"), noinline, noclone))
//clear RX interrupt
//set tx field to keep from accidentally clearing //mask out toggle feilds making them zero //clear rx bit removing active interrupt
#define EP0R_CLR_CTR_RX() USB->EP0R = (((USB->EP0R | USB_EP_CTR_TX) & USB_EPREG_MASK ) & ~USB_EP_CTR_RX )
//clear TX interrupt
#define EP0R_CLR_CTR_TX() USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX) & USB_EPREG_MASK ) & ~USB_EP_CTR_TX )
//VALID need to get both status bits set
//XOR the current value of status bits with 1 to write back inverted value, gets all status bits set
// OR in bits that need set, AND in bits to keep or avail for XOR, XOR toggles to invert
#define USB_EP0R_RXTX_VALID() USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & ~(USB_EP_DTOG_RX | USB_EP_DTOG_TX)) ^ (USB_EPTX_STAT | USB_EPRX_STAT))
#define USB_EP0R_RX_VALID() USB->EP0R = ((((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX)) & (USB_EPREG_MASK | USB_EPRX_STAT)) ^ USB_EPRX_STAT )
#define USB_EP0R_TX_VALID() USB->EP0R = ((((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX)) & (USB_EPREG_MASK | USB_EPTX_STAT)) ^ USB_EPTX_STAT )
#define USB_EP0R_RX_VALID_STATUS_OUT() USB->EP0R = ((((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX | USB_EP_KIND)) & (USB_EPREG_MASK | USB_EPRX_STAT)) ^ USB_EPRX_STAT )
#define USB_EP0R_EP_KIND_ANY() USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX)) & (USB_EPREG_MASK & ~USB_EP_KIND))
//DISABLE need to get both bits cleared
//write back current value of status bits to toggle all 1's to zeros
// OR in bits that need set AND in bits to keep or toggle from 1 to 0
#define USB_EP0R_RXTX_DIS() USB->EP0R = ((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & ~(USB_EP_DTOG_RX | USB_EP_DTOG_TX))
#define USB_EP0R_RX_DIS() USB->EP0R = ((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK | USB_EPRX_STAT))
#define USB_EP0R_TX_DIS() USB->EP0R = ((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK | USB_EPTX_STAT))
//NAK/STALL need to get one bit set, and the other cleared
//Easiest way would be to DISABLE, and then set desired bit, uses two accesses to EP0R
// DISABLE first OR in bits that need set AND in bits to keep or toggle
#define USB_EP0R_RX_NAK() USB_EP0R_RX_DIS(); USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK)) | USB_EP_RX_NAK)
#define USB_EP0R_TX_NAK() USB_EP0R_TX_DIS(); USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK)) | USB_EP_TX_NAK)
#define USB_EP0R_RXTX_NAK() USB_EP0R_RXTX_DIS(); USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK)) | (USB_EP_RX_NAK | USB_EP_TX_NAK))
#define USB_EP0R_RX_STALL() USB_EP0R_RX_DIS(); USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK)) | USB_EP_RX_STALL)
#define USB_EP0R_TX_STALL() USB_EP0R_TX_DIS(); USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK)) | USB_EP_TX_STALL)
#define USB_EP0R_RXTX_STALL() USB_EP0R_RXTX_DIS(); USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK)) | (USB_EP_RX_STALL | USB_EP_TX_STALL))
//USB_COUNTn_RX table entries are a little annoying..
//create some macros to simplify setting RX COUNT
#define BL_SIZE32 (uint16_t) 0x8000
#define BL_SIZE2 (uint16_t) 0x0000
#define NUM_BLOCKS 10U //shift number of blocks by this amount
#define RX_COUNT_MSK (uint16_t) 0x03FF
// Cannot setup for 0 bytes to be received, that's equivalent of STATUS OUT packet which isn't a true data reception
#define USB_RX_2TO62_MUL2B(oper) ((uint16_t) ((BL_SIZE2) | ((oper/2)<<NUM_BLOCKS)))
#define USB_RX_32TO992_MUL32B(oper) ((uint16_t) ((BL_SIZE32) | ((oper/32-1)<<NUM_BLOCKS)))
//#define USB_RX_2BYTES ((uint16_t) ((BL_SIZE2) | ((2/2)<<NUM_BLOCKS)))
//#define USB_RX_4BYTES ((uint16_t) ((BL_SIZE2) | ((4/2)<<NUM_BLOCKS)))
//#define USB_RX_6BYTES ((uint16_t) ((BL_SIZE2) | ((6/2)<<NUM_BLOCKS)))
//#define USB_RX_8BYTES ((uint16_t) ((BL_SIZE2) | ((8/2)<<NUM_BLOCKS)))
//#define USB_RX_16BYTES ((uint16_t) ((BL_SIZE2) | ((16/2)<<NUM_BLOCKS)))
//// Can set from 2-62B in increments of 2B, just haven't bothered defining them all here...
//#define USB_RX_32BYTES ((uint16_t) ((BL_SIZE32) | ((32/32-1)<<NUM_BLOCKS)))
//#define USB_RX_64BYTES ((uint16_t) ((BL_SIZE32) | ((64/32-1)<<NUM_BLOCKS)))
//#define USB_RX_96BYTES ((uint16_t) ((BL_SIZE32) | ((96/32-1)<<NUM_BLOCKS)))
//#define USB_RX_128BYTES ((uint16_t) ((BL_SIZE32) | ((128/32-1)<<NUM_BLOCKS)))
//#define USB_RX_256BYTES ((uint16_t) ((BL_SIZE32) | ((256/32-1)<<NUM_BLOCKS)))
//#define USB_RX_512BYTES ((uint16_t) ((BL_SIZE32) | ((512/32-1)<<NUM_BLOCKS)))
//// Can set from 32-992B in increments of 32B, just haven't bothered defining them all here...
//#define USB_RX_992BYTES ((uint16_t) ((BL_SIZE32) | ((992/32-1)<<NUM_BLOCKS)))
// while 1024 is max size of packet for USB 2.0, this part's designed USB buffer memory
// creates the limit of 992B xfr buffer + 32B buffer table (also in buffer ram) = 1024B size of USB buffer ram
//Would like to have USB code not use any .data nor .bss so the USB code can be separated from the application code
//this allows the USB code to update/bootload the application code/firmware more easily
//Currently doesn't use any .data, but does use ~18Bytes of .bss for static variables
//cutting out the log debug variable dropped it down to 14Bytes
//So let's place those 14Bytes worth of variables in the begining of USB RAM
#define NUM_BYTES_REQ 0 //variable placed in first 16bit index
#define NUM_BYTES_SENDING 1 //variable placed in second index...
//#define NUM_BYTES_EXPECTING 2 //variable cut
#define NUM_BYTES_XFRD 2
#define NEWADDR_REQTYPE 3 //two single byte variables stored in this index
#define VAR_REQ_DIR 4 //might be able to combine with above..?
//there's 6Bytes of available space, could be used for usbMsgPtr, but need to ensure half word access is used..
#define USBMSGPTR_L 5 //lower 16bit of pointer
#define USBMSGPTR_H 6 //upper 16bit of pointer
//now there's 7 indexes = 14Bytes used for usb_buff ram variables and the usb code shouldn't be using any .data nor .bss
//usbstm only uses the stack and usb_buff ram table
//There are 2 bytes unused, perhaps these can be utilized for initialization flags or other communication between
//usb driver and application code
#define USBFLAG 7
#define usbflag usb_buff[USBFLAG] //used for communication between USB driver and main application
//different values for usbflag
// 0x0000 reserved for flag cleared
#define INITUSB 0xA53C //used by main application to tell usb driver to initialize itself
//need 4 bytes for setup & write functions, bump the BTABLE another 8Bytes for now...
#define USBFUNCSETUP 8
#define usbfuncsetup usb_buff[USBFUNCSETUP] //will always be odd (Thumb)
#define USBFUNCWRITE 9
#define usbfuncwrite usb_buff[USBFUNCWRITE] //will always be odd (Thumb)
// #define RESETME 0x5FA4 //used by fwupdater to signal device to reset itself
//being an even number we know it's a safe value because all funcs are thumb
//#define FWPTR_LO 10
//#define fwptr_lo usb_buff[FWPTR_LO]
//#define FWPTR_HI 11
//#define fwptr_hi usb_buff[FWPTR_HI]
//buffer table itself is located in 1KB buffer above, but it's location is programmable
//the table must be aligned to an 8Byte boundary
//#define USB_BTABLE_ADDR ((uint16_t) 0x0000) //least 3 significant bits are forced to zero
#define USB_BTABLE_ADDR ((uint16_t) 0x0018) //this skips the first 16+8Bytes of usb buffer so can be used for vars above
#define USB_BTABLE_BASE USB_BTABLE_ADDR/2 //The base index is in 16bit half words
#define USB_BTABLE_SIZE 64 //32x 16bit halfwords
//NOTE!!! ADDR is the 8bit "BYTE" address, BASE is the index of the usb_buff array
//So BASE is always ADDR/2 will mess everything up if this isn't fully understood!
//Endpoint 0: setup as 8Bytes TX & RX following buffer table
// endpoint 0 size defined in usb_descriptors.h as it's needed there
//#define EP0_SIZE 0x08 //8Bytes same as usb 1.1 for now
#define EP0_TX_ADDR (USB_BTABLE_BASE + USB_BTABLE_SIZE)
#define EP0_TX_BASE (EP0_TX_ADDR / 2) //this is the actual half word index of the usb_buff array
//NOTE!!! control_xfr functions are hardcoded for EP0 size of 8Bytes currently, must update if changing
#define EP0_RX_ADDR (EP0_TX_ADDR + EP0_SIZE)
#define EP0_RX_BASE (EP0_RX_ADDR / 2) //this is the actual half word index of the usb_buff array
//debug place some variables in USB RAM, this broke when moving table to remove .bss RAM
//don't think it's really needed anymore..
////#define LOG0 (EP0_RX_ADDR + EP0_SIZE)
//#define LOG0 (64+16) / 2
//#define LOG4 LOG0 + 2
//#define LOG8 LOG0 + 4
//#define LOGC LOG0 + 6
//#define LOG10 LOG0 + 8
//Transmission buffer address n (USB_ADDRn_TX)
//Address offset: [USB_BTABLE] + n*8
//Note: In case of double-buffered or isochronous endpoints in the IN direction, this address location is referred to as USB_ADDRn_TX_0.
//In case of double-buffered or isochronous endpoints in the OUT direction, this address
//location is used for USB_ADDRn_RX_0.
#define USB_ADDR0_TX (USB_BTABLE_BASE + 0*8)
#define USB_ADDR1_TX (USB_BTABLE_BASE + 1*8)
#define USB_ADDR2_TX (USB_BTABLE_BASE + 2*8)
#define USB_ADDR3_TX (USB_BTABLE_BASE + 3*8)
#define USB_ADDR4_TX (USB_BTABLE_BASE + 4*8)
#define USB_ADDR5_TX (USB_BTABLE_BASE + 5*8)
#define USB_ADDR6_TX (USB_BTABLE_BASE + 6*8)
#define USB_ADDR7_TX (USB_BTABLE_BASE + 7*8)
//Bits 15:1 ADDRn_TX[15:1]: Transmission buffer address
//These bits point to the starting address of the packet buffer containing data to be transmitted
//by the endpoint associated with the USB_EPnR register at the next IN token addressed to it.
//Bit 0 Must always be written as <20><><EFBFBD><EFBFBD>0 since packet memory is half-word wide and all packet buffers
//must be half-word aligned.
//Transmission byte count n (USB_COUNTn_TX)
//Address offset: [USB_BTABLE] + n*8 + 2
//Note: In case of double-buffered or isochronous endpoints in the IN direction, this address location is referred to as USB_COUNTn_TX_0.
//In case of double-buffered or isochronous endpoints in the OUT direction, this address
//location is used for USB_COUNTn_RX_0.
#define USB_COUNT0_TX (USB_BTABLE_BASE + 0*8 + 1)
#define USB_COUNT1_TX (USB_BTABLE_BASE + 1*8 + 1)
#define USB_COUNT2_TX (USB_BTABLE_BASE + 2*8 + 1)
#define USB_COUNT3_TX (USB_BTABLE_BASE + 3*8 + 1)
#define USB_COUNT4_TX (USB_BTABLE_BASE + 4*8 + 1)
#define USB_COUNT5_TX (USB_BTABLE_BASE + 5*8 + 1)
#define USB_COUNT6_TX (USB_BTABLE_BASE + 6*8 + 1)
#define USB_COUNT7_TX (USB_BTABLE_BASE + 7*8 + 1)
//Bits 15:10These bits are not used since packet size is limited by USB specifications to 1023 bytes. Their
//value is not considered by the USB peripheral.
//Bits 9:0 COUNTn_TX[9:0]: Transmission byte count
//These bits contain the number of bytes to be transmitted by the endpoint associated with the
//USB_EPnR register at the next IN token addressed to it.
//Reception buffer address n (USB_ADDRn_RX)
//Address offset: [USB_BTABLE] + n*8 + 4
//Note: In case of double-buffered or isochronous endpoints in the OUT direction, this address
//location is referred to as USB_ADDRn_RX_1.
//In case of double-buffered or isochronous endpoints in the IN direction, this address location is used for USB_ADDRn_TX_1.
#define USB_ADDR0_RX (USB_BTABLE_BASE + 0*8 + 2)
#define USB_ADDR1_RX (USB_BTABLE_BASE + 1*8 + 2)
#define USB_ADDR2_RX (USB_BTABLE_BASE + 2*8 + 2)
#define USB_ADDR3_RX (USB_BTABLE_BASE + 3*8 + 2)
#define USB_ADDR4_RX (USB_BTABLE_BASE + 4*8 + 2)
#define USB_ADDR5_RX (USB_BTABLE_BASE + 5*8 + 2)
#define USB_ADDR6_RX (USB_BTABLE_BASE + 6*8 + 2)
#define USB_ADDR7_RX (USB_BTABLE_BASE + 7*8 + 2)
//Bits 15:1 ADDRn_RX[15:1]: Reception buffer address
//These bits point to the starting address of the packet buffer, which will contain the data
//received by the endpoint associated with the USB_EPnR register at the next OUT/SETUP
//token addressed to it.
//Bit 0 This bit must always be written as <20><><EFBFBD><EFBFBD>0 since packet memory is half-word wide and all packet
//buffers must be half-word aligned.
//Reception byte count n (USB_COUNTn_RX)
//Address offset: [USB_BTABLE] + n*8 + 6
//Note: In case of double-buffered or isochronous endpoints in the OUT direction, this address
//location is referred to as USB_COUNTn_RX_1.
//In case of double-buffered or isochronous endpoints in the IN direction, this address location is used for USB_COUNTn_TX_1.
#define USB_COUNT0_RX (USB_BTABLE_BASE + 0*8 + 3)
#define USB_COUNT1_RX (USB_BTABLE_BASE + 1*8 + 3)
#define USB_COUNT2_RX (USB_BTABLE_BASE + 2*8 + 3)
#define USB_COUNT3_RX (USB_BTABLE_BASE + 3*8 + 3)
#define USB_COUNT4_RX (USB_BTABLE_BASE + 4*8 + 3)
#define USB_COUNT5_RX (USB_BTABLE_BASE + 5*8 + 3)
#define USB_COUNT6_RX (USB_BTABLE_BASE + 6*8 + 3)
#define USB_COUNT7_RX (USB_BTABLE_BASE + 7*8 + 3)
//This table location is used to store two different values, both required during packet
//reception. The most significant bits contains the definition of allocated buffer size, to allow
//buffer overflow detection, while the least significant part of this location is written back by the
//USB peripheral at the end of reception to give the actual number of received bytes. Due to the
//restrictions on the number of available bits, buffer size is represented using the number of allocated
//memory blocks, where block size can be selected to choose the trade-off between fine-granularity/small-buffer
//and coarse-granularity/large-buffer. The size of allocated buffer is a part of the endpoint descriptor
//and it is normally defined during the enumeration process according to its maxPacketSize parameter value
//(See <20><><EFBFBD><EFBFBD>Universal Serial Bus Specification<6F><6E><EFBFBD><EFBFBD>).
//
//Bit 15 BL_SIZE: Block size
//This bit selects the size of memory block used to define the allocated buffer area.
// -If BL_SIZE=0, the memory block is 2-byte large, which is the minimum block
// allowed in a half-word wide memory. With this block size the allocated buffer size
// ranges from 2 to 62 bytes.
// -If BL_SIZE=1, the memory block is 32-byte large, which allows to reach the
// maximum packet length defined by USB specifications. With this block size the
// allocated buffer size theoretically ranges from 32 to 1024 bytes, which is the longest
// packet size allowed by USB standard specifications. However, the applicable size is limited by the available buffer memory.
//
//Bits 14:10 NUM_BLOCK[4:0]: Number of blocks
//These bits define the number of memory blocks allocated to this packet buffer. The actual amount of
//allocated memory depends on the BL_SIZE value as illustrated in Table127.
//
//Bits 9:0 COUNTn_RX[9:0]: Reception byte count
//These bits contain the number of bytes received by the endpoint associated with the
//USB_EPnR register during the last OUT/SETUP transaction addressed to it.
//#define __packed __attribute((packed))__
typedef struct usbRequest_t{
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
}usbRequest_t;
//}__attribute((__packed__))usbRequest_t;
// bmRequestType
//D7 Data Phase Transfer Direction
//0 = Host to Device
//1 = Device to Host
#define REQ_DIR_MASK 0x80
#define REQ_DIR_OUT 0x00
#define REQ_DIR_IN 0x80
//D6..5 Type
//0 = Standard
//1 = Class
//2 = Vendor
//3 = Reserved
#define REQ_TYPE_MASK 0x60
#define REQ_TYPE_STD 0x00
#define REQ_TYPE_CLASS 0x20
#define REQ_TYPE_VEND 0x40
#define REQ_TYPE_RES 0x60
//D4..0 Recipient
//0 = Device
//1 = Interface
//2 = Endpoint
//3 = Other
#define REQ_RECIP 0x0F
#define REQ_RECIP_DEV 0x00
#define REQ_RECIP_INT 0x01
#define REQ_RECIP_EP 0x02
#define REQ_RECIP_OTH 0x03
//4..31 = Reserved
//defined to be same as Vusb
//not sure this is actually how we want to do things..
#define USB_NO_MSG 255
#define usbPoll() NOP()
#define usbMsgPtr_t uint16_t *
//extern usbMsgPtr_t usbMsgPtr; //this variable is defined in usbstm.c
//putting extern here allows any file that imports usbstm.h access to usbMsgPtr
//application code can access the entire usb_buff as well as the usbMsgPtr_H/L
//extern used here to declare usb_buff so other files can use it, definition is in usbstm.c
extern uint16_t volatile (* const usb_buff);
#define usbMsgPtr_L usb_buff[USBMSGPTR_L] //place this variable in USB RAM
#define usbMsgPtr_H usb_buff[USBMSGPTR_H] //place this variable in USB RAM
//These declarations are solely for compilation purposes of usb code so it knows what
//these functions contained in the application code look like
extern uint16_t usbFunctionSetup(uint8_t data[8]);
extern uint8_t usbFunctionWrite(uint8_t *data, uint8_t len);
//don't want any application functions/files calling this code!
//void usb_reset_recovery();
//void init_usb();
#endif