STM32F103ZET6(development board ) with FSMC,NAND/NOR FLASH
STM32
development board based on STMicroelectronics (ST) has introduced the
highest series of ARM CortexM3 chip configuration as the core component
STM32F103ZET6
On-board resources:
*
CPU: STM32F103ZET6; (LQFP144-pin, on-chip integrated 512K flash,
64KRAM, 12Bit A / D, D / A; PWM, CAN, USB, SDIO, FSMC and other
resources)
*
Outside the expanded board 512K SRAM, 2M NOR FLASH (on-board support
for the largest 1024k SRAM, 16M of NOR FLASH) to meet the large capacity
data acquisition, processing and analysis requirements
*
Board outside 128M NAND FLASH expand to meet the rich color of the
picture storage, data storage form, document management applications and
so on
*FSMC
control, color touch module configuration TSC2046 controller,
support for a SD card (SPI mode) can be used to store pictures, in
support of AT45DBxxx of a DATA FLASH (can be used for storage)
* All the way CAN communication interface, the drive chip SN65VHD230
* Two-way RS232 interface
* All the way RS485 communication interface
* A SD card connector SDIO control
* A I2C memory interface, the standard 24LC02 (EEPROM)
* A SPI memory interface, AT45DB161D or M45PE16V (DATA FLASH)
* All the way adjustment potentiometer ADC input
* Three-way leads to ADC input terminals
* Two-way terminal block PWM output leads
* Two-way leads to DAC output terminals
*
A buzzer, the five users LED lights, a power indicator light, a USB
communication indicator, four user keys, a system reset button
* Power Select jumper to support the external 5V power supply, USB power supply or power supply by JLINK
* Board Size: 13CM X 10CM
Thursday, November 21, 2013
Tuesday, November 12, 2013
[peekstm32] the problem was data toggle
The odd thing was that the problem lay with JUST the peek function or host "IN" packets. I played around with the stm32_endp_isr_user_out() routines "IN" packet handling section. Wasnt sure of the state of DTOG_TX so I figured Id force it to 0 instead 1.
Immediately the first peek command from the next run worked and failed there after. After playing around with DTOG_TX forced to 1, toggled I finally deleted it, essentially leaving it floating and that worked
Basically delete this line from stm32_endp_isr_user_out()
stm32_usb_set_epr_dtog(wdEndP,\
1,\
STM32_USB_EPR_DTOG_TX_OFFSET);
End Result - arm m-3 minicom:
--------RESET----------- 27uS
--------RESET----------- 28uS
80 06 00 01 00 00 40 00
--------RESET----------- 28uS
00 05 3E 00 00 00 00 00
usb device address = 3E
80 06 00 01 00 00 12 00
80 06 00 02 00 00 09 00
80 06 00 02 00 00 20 00
80 06 00 03 00 00 FF 00
80 06 02 03 09 04 FF 00
80 06 01 03 09 04 FF 00
80 06 03 03 09 04 FF 00
00 09 01 00 00 00 00 00
00 08 ED FE 04 5C 00 40
user req peek [40005C04]=7021
00 08 ED FE 04 5C 00 40
user req peek [40005C04]=3061
00 08 ED FE 04 5C 00 40
user req peek [40005C04]=7021
00 08 ED FE 04 5C 00 40
user req peek [40005C04]=3061
00 08 ED FE 40 60 00 40
user req peek [40006040]=00
01 0C ED FE 40 60 00 40
user req poke [40006040]=B0
00 08 ED FE 40 60 00 40
user req peek [40006040]=B0
On the host linux pc side:
sudo ./peekstm32.out 0x40005c04
[40005c04] = 7021
sudo ./peekstm32.out 0x40005c04
[40005c04] = 3061
sudo ./peekstm32.out 0x40005c04
[40005c04] = 7021
sudo ./peekstm32.out 0x40005c04
[40005c04] = 3061
sudo ./peekstm32.out 0x40006040
[40006040] = 0
sudo ./peekstm32.out 0x40006040 0xb0
sudo ./peekstm32.out 0x40006040
[40006040] = b0
DONE!!!
Immediately the first peek command from the next run worked and failed there after. After playing around with DTOG_TX forced to 1, toggled I finally deleted it, essentially leaving it floating and that worked
Basically delete this line from stm32_endp_isr_user_out()
stm32_usb_set_epr_dtog(wdEndP,\
1,\
STM32_USB_EPR_DTOG_TX_OFFSET);
End Result - arm m-3 minicom:
--------RESET----------- 27uS
--------RESET----------- 28uS
80 06 00 01 00 00 40 00
--------RESET----------- 28uS
00 05 3E 00 00 00 00 00
usb device address = 3E
80 06 00 01 00 00 12 00
80 06 00 02 00 00 09 00
80 06 00 02 00 00 20 00
80 06 00 03 00 00 FF 00
80 06 02 03 09 04 FF 00
80 06 01 03 09 04 FF 00
80 06 03 03 09 04 FF 00
00 09 01 00 00 00 00 00
00 08 ED FE 04 5C 00 40
user req peek [40005C04]=7021
00 08 ED FE 04 5C 00 40
user req peek [40005C04]=3061
00 08 ED FE 04 5C 00 40
user req peek [40005C04]=7021
00 08 ED FE 04 5C 00 40
user req peek [40005C04]=3061
00 08 ED FE 40 60 00 40
user req peek [40006040]=00
01 0C ED FE 40 60 00 40
user req poke [40006040]=B0
00 08 ED FE 40 60 00 40
user req peek [40006040]=B0
On the host linux pc side:
sudo ./peekstm32.out 0x40005c04
[40005c04] = 7021
sudo ./peekstm32.out 0x40005c04
[40005c04] = 3061
sudo ./peekstm32.out 0x40005c04
[40005c04] = 7021
sudo ./peekstm32.out 0x40005c04
[40005c04] = 3061
sudo ./peekstm32.out 0x40006040
[40006040] = 0
sudo ./peekstm32.out 0x40006040 0xb0
sudo ./peekstm32.out 0x40006040
[40006040] = b0
DONE!!!
Monday, November 11, 2013
[peekstm32] libusb_bulk_transfer() command failed with -7
/usr/include/libusb-1.0/libusb.h lists -1 as
LIBUSB_ERROR_TIMEOUT = -7,
But timeout is set to 1000ms or 1 second in my peekstm32.c program. My primary concern is that I am not seeing any communication on the stm32 side with bulk endpoints. Need to check their configuration settings in the EPRX registers later.
I am seeing this now ... but the problem persists EVEN though the usb sniffer clearly shows data transmission without any errors, with peek and pokes from peekstm32.c
LIBUSB_ERROR_TIMEOUT = -7,
But timeout is set to 1000ms or 1 second in my peekstm32.c program. My primary concern is that I am not seeing any communication on the stm32 side with bulk endpoints. Need to check their configuration settings in the EPRX registers later.
I am seeing this now ... but the problem persists EVEN though the usb sniffer clearly shows data transmission without any errors, with peek and pokes from peekstm32.c
using linux libusb to test communication with the my stm32 firmware
Figured Id put together a small example program to allow me to test out my usb device/firmware by using usb communication (on the linux host) to peek and poke offsets in stm32 space. Culminating in toggling LED1 off and on from the linux host.
With that in mind I installed libusb
apt-cache search libusb
apt-get install libusb-1.0.0 libusb-1.0.0-dev
And wrote peekstm32.c
usage is a follows:
[peekstm32] options
adddress value[optional]
But it seemed to be failing on the libus_claim_device() routine. Thats also when I discovered that not all the configuration data had been transferred.
lsusb -vvv -dc0de: returns
Bus 001 Device 013: ID c0de:feed
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0xc0de
idProduct 0xfeed
bcdDevice 1.00
iManufacturer 1 Igbo Embedded
iProduct 2 My Device
iSerial 3 1234
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 32
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 500mA
Device Status: 0x0000
(Bus Powered)
The Interface and Endpoint descriptors are missing. Also I noticed on the minicom usb communication dump that the linux host send two get configuration descriptor commands. one for 9 bytes the other for 32 so the first succeeds (IN) but the second fails:
80 06 00 02 00 00 09 00
80 06 00 02 00 00 20 00
Need to look at this closely before continuing with the userland program. Found the problem - bug on line 825 of IE_stm32_usb.c: Removed this line
if(wdSize > (*ptrTemp))
wdSize = (*ptrTemp);
And all is well. I actually found that bug by placing tclib_printf() of wdCount inside stm32_dequeue_IN_transfers.
Now
sudo lsusb -dc0de: -vvv returns
Bus 001 Device 017: ID c0de:feed
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0xc0de
idProduct 0xfeed
bcdDevice 1.00
iManufacturer 1 Igbo Embedded
iProduct 2 My Device
iSerial 3 1234
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 32
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 2
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 2
Device Status: 0x0000
(Bus Powered)
With that in mind I installed libusb
apt-cache search libusb
apt-get install libusb-1.0.0 libusb-1.0.0-dev
And wrote peekstm32.c
usage is a follows:
[peekstm32] options
adddress value[optional]
But it seemed to be failing on the libus_claim_device() routine. Thats also when I discovered that not all the configuration data had been transferred.
lsusb -vvv -dc0de: returns
Bus 001 Device 013: ID c0de:feed
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0xc0de
idProduct 0xfeed
bcdDevice 1.00
iManufacturer 1 Igbo Embedded
iProduct 2 My Device
iSerial 3 1234
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 32
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 500mA
Device Status: 0x0000
(Bus Powered)
The Interface and Endpoint descriptors are missing. Also I noticed on the minicom usb communication dump that the linux host send two get configuration descriptor commands. one for 9 bytes the other for 32 so the first succeeds (IN) but the second fails:
80 06 00 02 00 00 09 00
80 06 00 02 00 00 20 00
Need to look at this closely before continuing with the userland program. Found the problem - bug on line 825 of IE_stm32_usb.c: Removed this line
if(wdSize > (*ptrTemp))
wdSize = (*ptrTemp);
And all is well. I actually found that bug by placing tclib_printf() of wdCount inside stm32_dequeue_IN_transfers.
Now
sudo lsusb -dc0de: -vvv returns
Bus 001 Device 017: ID c0de:feed
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0xc0de
idProduct 0xfeed
bcdDevice 1.00
iManufacturer 1 Igbo Embedded
iProduct 2 My Device
iSerial 3 1234
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 32
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 2
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 2
Device Status: 0x0000
(Bus Powered)
peekstm32.c
/*
***********************************************************************
*name: peekstm32
*author: Samuel Igwe
*date: 11/11/2013 A.D
*description: stm32 host to usb peek and poke routine.
*note: peekstm32 address = read address
* peekstm32 address value = write value to address
*compiled as: gcc -o peekstm32.out -lusb-1.0 linux/peekstm32.c
***********************************************************************
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
/*#define constants*/
#define STMUSB_VENDOR_ID 0xc0de
#define STMUSB_PRODUCT_ID 0xfeed
#define STMUSB_BULK_ENDP_OUT 0x1
#define STMUSB_BULK_ENDP_IN 0x81
#define STMUSB_CMD_PEEK 0
#define STMUSB_CMD_POKE 1
#define STMUSB_TIMEOUT 1000
/*structure*/
struct STR_PEEKSTM32
{
unsigned int wdAddress;
unsigned int wdValue;
unsigned int wdMaxPktSize;
struct libusb_device_handle *ptrHandle;
struct libusb_device *ptrDevice;
}strPeekStm32;
void func_atexit(void);
/*
***********************************************************************
*description: main routine
*inputs: int argc = count
* char *argv[] = pointer to command line parameters
***********************************************************************
*/
main(int argc, char *argv[])
{
unsigned int wdCount, wdTemp;
char sbBuffer[64];
/*
***********************************************************************
*check commandline parameters
***********************************************************************
*/
memset(&strPeekStm32, 0, sizeof(strPeekStm32));
switch(argc)
{
case 2:
case 3:
{
strPeekStm32.wdAddress = \
(unsigned int)strtol(argv[1], (char **)NULL, 16);
if(argc == 3)
{
strPeekStm32.wdValue = \
(unsigned int)strtol(argv[2], (char **)NULL, 16);
}
break;
}
default:
case 0:
case 1:
{
printf("[peekstm32]\toptions\n\t\tadddress value[optional]\n");
return 0;
}
}
/*
***********************************************************************
*initialize variables and atexit routine
***********************************************************************
*/
if(atexit(func_atexit) != 0)
{
printf("[peekstm32]\tatexit() failed\n");
return 0;
}
/*
***********************************************************************
*initialize library
***********************************************************************
*/
if((wdTemp = libusb_init(NULL)) != 0)
{
printf("[peekstm32]\tlibusb_init() failed with %d\n",\
wdTemp);
return 0;
}
if((strPeekStm32.ptrHandle=libusb_open_device_with_vid_pid(NULL,\
STMUSB_VENDOR_ID,\
STMUSB_PRODUCT_ID)) == NULL)
{
printf("[peekstm32]\tlibusb_open_device_vid_pid() failed\n");
return 0;
}
if((strPeekStm32.ptrDevice = libusb_get_device(strPeekStm32.ptrHandle)) == NULL)
{
printf("[peekstm32]\tlibusb_get_device() failed\n");
return 0;
}
if((wdTemp = libusb_kernel_driver_active(strPeekStm32.ptrHandle, 0)) !=0)
{
if((wdTemp = libusb_detach_kernel_driver(strPeekStm32.ptrHandle, 0)) !=0)
{
printf("[peekstm32]\tlibusb_detach_kernel_driver() failed with %d\n",\
wdTemp);
return 0;
}
}
else
{
if((wdTemp = libusb_claim_interface(strPeekStm32.ptrHandle, 0)) != 0)
{
printf("[peekstm32]\tlibusb_claim_interface() failed with %d\n",\
wdTemp);
return 0;
}
}
/*
***********************************************************************
*get usb resources limits
***********************************************************************
*/
strPeekStm32.wdMaxPktSize = 0;
for(wdCount=0; wdCount < 16; wdCount++)
{
wdTemp = libusb_get_max_packet_size(strPeekStm32.ptrDevice, wdCount);
if(wdTemp != LIBUSB_ERROR_NOT_FOUND && wdTemp != LIBUSB_ERROR_OTHER)
strPeekStm32.wdMaxPktSize = wdTemp;
}
if(strPeekStm32.wdMaxPktSize <8)
{
printf("[peekstm32]\tlibusb_get_max_packet_size() failed to return adequate value\n");
return;
}
/*
***********************************************************************
*execute OUT transaction:COMMAND format is as follows:
* byte 0 = command
* byte 1 = length of data in bytes
* byte 2 = 0xed
* byte 3 = 0xfe
* byte 4 = 32bit address
* byte 5 =
* byte 6 =
* byte 7 =
***********************************************************************
*/
if(argc == 2) /*IN*/
{
sbBuffer[0] = STMUSB_CMD_PEEK;
sbBuffer[1] = 8; /*8*/
}
else
{
sbBuffer[0] = STMUSB_CMD_POKE;
sbBuffer[1] = 12; /*8 + 4 byte (dword)value*/
}
sbBuffer[2] = 0xed;
sbBuffer[3] = 0xfe;
memcpy(sbBuffer+4, &strPeekStm32.wdAddress, sizeof(int));
wdTemp = libusb_bulk_transfer(strPeekStm32.ptrHandle,\
STMUSB_BULK_ENDP_OUT,\
sbBuffer,\
8,\
&wdCount,\
STMUSB_TIMEOUT);
if(wdTemp != 0)
{
printf("[peekstm32]\tlibusb_bulk_transfer() command failed with %d\n",\
wdTemp);
return 0;
}
/*
***********************************************************************
*execute IN or OUT transaction depending on whether PEEK or POKE sought
***********************************************************************
*/
if(argc == 2) /*IN*/
{
if((wdTemp =libusb_bulk_transfer(strPeekStm32.ptrHandle,\
STMUSB_BULK_ENDP_IN,\
(char *)&(strPeekStm32.wdValue),\
4,\
&wdCount,\
STMUSB_TIMEOUT)) != 0)
{
if(wdCount == 0)
{
printf("[peekstm32]\tlibusb_bulk_transfer() data failed with %d\n",\
wdTemp);
return 0;
}
}
printf("[%x] = %x\n", strPeekStm32.wdAddress,\
strPeekStm32.wdValue);
return 0;
}
else /*OUT*/
{
memcpy(sbBuffer, &strPeekStm32.wdValue, sizeof(int));
if((wdTemp = libusb_bulk_transfer(strPeekStm32.ptrHandle,\
STMUSB_BULK_ENDP_OUT,\
(char *)&(strPeekStm32.wdValue),\
4,\
&wdCount,\
STMUSB_TIMEOUT)) != 0)
{
printf("[peekstm32]\tlibusb_bulk_transfer() data failed with %d\n",\
wdTemp);
return 0;
}
}
/*
***********************************************************************
*atexit
***********************************************************************
*/
return 0;
}
/*
***********************************************************************
*description: at exit routine
***********************************************************************
*/
void func_atexit(void)
{
if(strPeekStm32.ptrHandle != NULL)
{
libusb_release_interface(strPeekStm32.ptrHandle, 0);
libusb_close(strPeekStm32.ptrHandle);
}
return;
}
Monday, November 4, 2013
USB Enumeration Done
Finally got USB enumeration working on this stm32 cortex-m3 board. Spend the night working through a host of errors and bugs and reading and re-reading the manual and parts of Jan Axelsons USB complete book.
The invariant settings code in
stm32_usb_enable_endp
stm32_usb_clean_epr_ctr
stm32_usb_set_epr_dtog
stm32_usb_set_epr_stat
was flawed. I had left out the check against toggling RX and TX status. Later I had to examine the stm32_usb_post_reset_setup() code fearing I had omitted some detail. I did but there were not show stoppers. It was really the little things like
1. CLEARING RX and TX SPURIOUS interrupts on USB RESET in the stm32_usb_post_reset_setup() code. This was preventing me from getting further IN and OUT interrupts.
2. setting the data toggle to 1 for TX before calling stm32_usb_send_packet or stm32_usb_queue_IN_transfers. And later realizing that the hardware will auto toggle it afterwards and I neednt do anything more than set it to 1 for the initial transfer or start of transfer
3. cancelling queue IN transfers whenever a new OUT/SETUP command comes through.
4. omitting the check for SETUP and just relying on CTR_RX for incoming control commands
5. fixing a bug in stm32_usb_dequeue_IN_transfers that was preventing me from transfer more than just the first data block
I will be using libusb to write the data communication software to talk to this device. I have yet to decide what sort of data I am going to pipe out. Maybe simulate a joystick or take the genesis controller and run it through ... after decoding. Or better yet design something in fpga and interface to this stm32 or the new one I purchased ...
The invariant settings code in
stm32_usb_enable_endp
stm32_usb_clean_epr_ctr
stm32_usb_set_epr_dtog
stm32_usb_set_epr_stat
was flawed. I had left out the check against toggling RX and TX status. Later I had to examine the stm32_usb_post_reset_setup() code fearing I had omitted some detail. I did but there were not show stoppers. It was really the little things like
1. CLEARING RX and TX SPURIOUS interrupts on USB RESET in the stm32_usb_post_reset_setup() code. This was preventing me from getting further IN and OUT interrupts.
2. setting the data toggle to 1 for TX before calling stm32_usb_send_packet or stm32_usb_queue_IN_transfers. And later realizing that the hardware will auto toggle it afterwards and I neednt do anything more than set it to 1 for the initial transfer or start of transfer
3. cancelling queue IN transfers whenever a new OUT/SETUP command comes through.
4. omitting the check for SETUP and just relying on CTR_RX for incoming control commands
5. fixing a bug in stm32_usb_dequeue_IN_transfers that was preventing me from transfer more than just the first data block
I will be using libusb to write the data communication software to talk to this device. I have yet to decide what sort of data I am going to pipe out. Maybe simulate a joystick or take the genesis controller and run it through ... after decoding. Or better yet design something in fpga and interface to this stm32 or the new one I purchased ...
Sunday, November 3, 2013
STAT_TX and STAT_RX are toggle bits
IN transfers werent taking place, worse they were flagged as STALLS. It occurred to me that the STAT_TX and STAT_RX bits might be at fault. STAT_RX really doesnt matter because only 00 = disabled is the only mode that will stall/halt/nak a setup out transfer.
At stm32_usb_init() I had set STAT_TX to NAK (01). Later after calls to stm32_usb_endp_send_packet() I would write VALID(11) to the 2 relevant bits of the EPR0 register representing STAT_TX. The problem is that a value of 1 for either bit indicates a toggle NOT a set. So it wasnt an error in the documentation - which was true to form. But rather an error in my interpretation of it. Sure enough minicom dumps show no print outs from within IN isr.
As a final test and confirmation I decided to stop execution under gdb and write the value 0x11 to STAT_TX and STAT_RX (bits 4+5 and 12+13) of the EPR0 register. Just to see if its set or toggled. Sure enough my worst fears were confirmed
This led to writing the following routine to encapsulate the process of properly setting STAT_TX and STAT_RX
/*
**********************************************************************
*description: routine to properly set the EP_TYPE bits in the
* Endpoint register.
*input: unsigned int wdEndP = endpoint number
* unsigned int wdEndPType = the following
* STM32_USB_EPR_EP_TYPE_BULK
* STM32_USB_EPR_EP_TYPE_CONTROL
* STM32_USB_EPR_EP_TYPE_ISO
* STM32_USB_EPR_EP_TYPE_INTERRUPT
*output: void
*
*note: the CTR_RX and CTR_TX bits are governed by the rules
* 1 = dont change 0 = clear
**********************************************************************
*/
void stm32_usb_enable_endp(unsigned int wdEndP,\
unsigned int wdEndPType)
{
unsigned int wdTemp;
/*retrieve the current register value*/
wdTemp = *(PTR_STM32_USB_EP0R + wdEndP);
/*invariants - values that will not modify these reg bits*/
wdTemp &= ~(STM32_USB_EPR_STAT_TX_MASK | \
STM32_USB_EPR_STAT_RX_MASK | \
(STM32_USB_EPR_DTOG_TX | STM32_USB_EPR_DTOG_RX));
wdTemp |= (STM32_USB_EPR_CTR_TX | STM32_USB_EPR_CTR_RX);
/*set EndPType and number*/
wdTemp |= (wdEndPType << STM32_USB_EPR_EP_TYPE_OFFSET);
wdTemp |= wdEndP;
/*set the current register value*/
*(PTR_STM32_USB_EP0R + wdEndP) = (wdTemp | wdEndP);
}
/*
**********************************************************************
*description: routine to properly set the RX and TX STAT bits in the
* Endpoint register.
*input: unsigned int wdEndP = endpoint number
* unsigned int wdMask = the following
* STM32_USB_EPR_CTR_RX
* STM32_USB_EPR_CTR_TX
*output: void
*
*note: the CTR_RX and CTR_TX bits are governed by the rules
* 1 = dont change 0 = clear
**********************************************************************
*/
void stm32_usb_clear_epr_ctr(unsigned int wdEndP,\
unsigned int wdMask)
{
unsigned int wdTemp;
/*retrieve the current register value*/
wdTemp = *(PTR_STM32_USB_EP0R + wdEndP);
#ifdef DONT_DEBUG
tclib_printf("stm32_usb_clear_epr_ctr initial value =%x\n", wdTemp);
#endif
/*invariants - values that will not modify these reg bits*/
wdTemp &= ~(STM32_USB_EPR_STAT_TX_MASK | \
STM32_USB_EPR_STAT_RX_MASK | \
(STM32_USB_EPR_DTOG_TX | STM32_USB_EPR_DTOG_RX));
wdTemp |= (STM32_USB_EPR_CTR_TX | STM32_USB_EPR_CTR_RX);
wdTemp &= ~wdMask;
#ifdef DONT_DEBUG
tclib_printf("stm32_usb_clear_epr_ctr final value =%x\n", wdTemp);
#endif
/*set the current register value*/
*(PTR_STM32_USB_EP0R + wdEndP) = (wdTemp | wdEndP);
}
/*
**********************************************************************
*description: routine to properly set or toggle the DTOG_RX | DTOG_TX
* bits of the Endpoint register.
*input: unsigned int wdEndP = endpoint number
* unsigned int wdNewStat = the following
* 0 = set to 0
* 1 = set to 1
* -1 = toggle
* unsigned int wdOffset = DTOG_RX or DTOG_TX STAT
* STM32_USB_EPR_DTOG_RX_OFFSET
* STM32_USB_EPR_DTOG_TX_OFFSET
*output: void
*
*note: the DTOG_RX and DTOG_TX bits are governed by the rules
* 0 = dont change 1 = TOGGLE
**********************************************************************
*/
void stm32_usb_set_epr_dtog(unsigned int wdEndP,\
int wdNewStat,\
unsigned int wdOffset)
{
unsigned int wdMask, wdTemp;
/*retrieve the current register value*/
wdMask = *(PTR_STM32_USB_EP0R + wdEndP);
wdTemp = wdMask;
/*wdMask has STAT position extracted*/
if(wdOffset == STM32_USB_EPR_DTOG_RX_OFFSET)
wdMask &= STM32_USB_EPR_DTOG_RX;
else
wdMask &= STM32_USB_EPR_DTOG_TX;
/*normalize then compute XOR of value and mask*/
wdMask >>= wdOffset;
if(wdNewStat != -1 && wdMask == wdNewStat)
return;
if(wdNewStat == -1)
wdNewStat = 1;
wdMask ^= wdNewStat;
wdMask <<= wdOffset;
/*mask out non important bits*/
if(wdOffset == STM32_USB_EPR_DTOG_RX_OFFSET)
wdMask &= STM32_USB_EPR_DTOG_RX;
else
wdMask &= STM32_USB_EPR_DTOG_TX;
/*invariants - values that will not modify these reg bits*/
wdTemp &= ~(STM32_USB_EPR_STAT_TX_MASK | \
STM32_USB_EPR_STAT_RX_MASK | \
(STM32_USB_EPR_DTOG_TX | STM32_USB_EPR_DTOG_RX));
wdTemp |= (STM32_USB_EPR_CTR_TX | STM32_USB_EPR_CTR_RX);
/*set user settings*/
wdTemp |= wdMask;
/*update register*/
*(PTR_STM32_USB_EP0R + wdEndP) = (wdTemp | wdEndP);
}
/*
**********************************************************************
*description: routine to properly set the RX and TX STAT bits in the
* Endpoint register.
*input: unsigned int wdEndP = endpoint number
* unsigned int wdNewStat = the following
* STM32_USB_EPR_STAT_RX_DISABLE
* STM32_USB_EPR_STAT_TX_DISABLE
*
* STM32_USB_EPR_STAT_RX_STALL
* STM32_USB_EPR_STAT_TX_STALL
*
* STM32_USB_EPR_STAT_RX_NAK
* STM32_USB_EPR_STAT_TX_NAK
*
* STM32_USB_EPR_STAT_RX_VALID
* STM32_USB_EPR_STAT_TX_VALID
* unsigned int wdOffset = RX or TX STAT
* STM32_USB_EPR_STAT_RX_OFFSET
* STM32_USB_EPR_STAT_TX_OFFSET
*output: void
*
*note: the RX_STAT and TX_STAT bits are governed by the rules
* 0 = dont change 1 = TOGGLE
* A major error was not taking this into consideration
**********************************************************************
*/
void stm32_usb_set_epr_stat(unsigned int wdEndP,\
unsigned int wdNewStat,\
unsigned int wdOffset)
{
unsigned int wdMask, wdTemp;
/*retrieve the current register value*/
wdMask = *(PTR_STM32_USB_EP0R + wdEndP);
wdTemp = wdMask;
/*wdMask has STAT position extracted*/
if(wdOffset == STM32_USB_EPR_STAT_RX_OFFSET)
wdMask &= STM32_USB_EPR_STAT_RX_MASK;
else
wdMask &= STM32_USB_EPR_STAT_TX_MASK;
/*normalize then compute XOR of value and mask*/
wdMask >>= wdOffset;
wdMask ^= wdNewStat;
wdMask <<= wdOffset;
/*mask out non important bits*/
if(wdOffset == STM32_USB_EPR_STAT_RX_OFFSET)
wdMask &= STM32_USB_EPR_STAT_RX_MASK;
else
wdMask &= STM32_USB_EPR_STAT_TX_MASK;
/*invariants - values that will not modify these reg bits*/
wdTemp &= ~(STM32_USB_EPR_STAT_TX_MASK | \
STM32_USB_EPR_STAT_RX_MASK | \
(STM32_USB_EPR_DTOG_TX | STM32_USB_EPR_DTOG_RX));
wdTemp |= (STM32_USB_EPR_CTR_TX | STM32_USB_EPR_CTR_RX);
/*set user settings*/
wdTemp |= wdMask;
/*update register*/
*(PTR_STM32_USB_EP0R + wdEndP) = (wdTemp | wdEndP);
}
Subscribe to:
Posts (Atom)







