The IRQ with the highest priority at 0x63 within table 16
is marked as "reserved" within the data sheet.
YET the initialization code explicitely uses it and warns
about its removal:
; Turbo Debug Interrupt Service routine - Do Not Remove
CSEG AT 063H ; debug interrupt vector
...
Seems some undocumented but nevertheless important
feature is lurking there.
Another topic: maybe add SFR16 definitions for the timers
and the PCA unit (similar to those in C8051F520.h)
for the uPSD as well?
Greetings,
Frieder
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
That violates the "no definitions in a header file" paradigm. If the file is included in two source files the linker will generate an error.
If however you only insert the prototype and the header is included in the source containing main, the vector will be generated and the linker will require the ISR to be defined.
I'm not up to speed with "inline" yet, but maybe that can solve this issue.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I noticed there is no P2 and no _XPAGE in the uPSD33xx.h. It seems the uPSD cannot use MOVX @Ri to access anything beyond the first 256 bytes. But it does have dual DPTR's. To make this work you need to adapt crtxclear.asm and crtxinit.asm in the libraries. If you want you can also adapt crtxstack.
Maarten
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am not 100% certain for 33xx, but in 32xx I am sucessfully using MOVX @Ri to access all external code memory with P2 as a higher address.
The documentation in this regard is unfortunately unclear, but in fact, although not connected to external pins, the P2 is present and connected internally to the PSD section as A8-A15.
I would be very surprised if this would be otherwise in 33xx (and for that matter, 34xx, too). After all, these are normal '51s (with some enhancements), connected to the PSD (=FLASH+RAM+GAL in one chip) in a multichip module form.
JW
PS. I'd add at least the offsets to the PSD port registers to the .h, too.
PS. OK, OK, I know. I should do it. Sorry, not today...
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I looked again and crtclear.asm doesn't need adaptation anymore than crtxstack does, assuming it's ok to write 0x00 to the reserved sfr at 0xA0.
I'll upload a new version of crtxinit.asm later today that conditionally can use dual data pointers instead of movx @Ri. It will not be much smaller or faster either way as it will not use auto-toggle or auto-increment features. And it requires an sfr named DPS to be defined instead of DPTC/AUXR1 with bit 0 as the selector.
Maarten
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
> The datasheet says otherwise. 0xA0 is RESERVED.
> And it explicitly mentions it cannot access beyond the first 256 bytes (page 30).
Well, then I AM very surprised. :-)
In the afternoon when I wrote that I checked with my uPSD33xx datasheet and P2 WAS there, and - now I looked better and that is a preliminary datasheet from 2003, I never needed a newer one...
I think the difference is beceause of the memory manager built into the 33xx/34xx (prefetch & jump cache).
I still think the .h can be augmented with definitions for the PSD register offsets... Or, even better, declare the registers as variables in XDATA memory, based on a base address for the registers to be passed to the .h - something like:
#ifndef PSD_CSIOP
#define PSD_CSIOP 0x1000 // some arbitrary default value
#endif
xdata at PSD_CSIOP+0xE2 unsigned char PSD_VM;
etc.
and the usage would be
someprogram.c:
#define PSD_CSIOP 0x3000
#include <upsd3xx.h>
Is this a good idea?
JW
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
please use the macro SFRX from compiler.h. That's what it's for.
I assume these registers can be mapped to a variable base address then. Do they actually have a default base or are you required to always set it? If there is no default I would tend to leave out the default value from the header file along with all SFRX definitions. This forces the user to think about what he/she's doing and supply the base. It will generate an error otherwise, unless these xdata registers are not used at all.
Now who volunteers?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Think of it as the registers are chip-selected from a GAL(PLD)-based address decoder, so the base address is determined by having configured (created a "bitstream") for the the GAL(PLD).
So, at the end of the day, the base address is user defined and, yes, (s)he should enter it explicitly. It is very unlikely that somebody would use a uPSD and NOT use any of these registers - at least they are needed to write and read to/from pins other than P1/P3 (i.e. roughly half of the I/O of the chip)...
Is there any standard mechanism to throw an explicit error, possibly explaining the cause of the error to the unaware user? Something like:
#ifndef PLD_CSIOP
#throw_error You should define PLD_CSIOP according to the chip configuration
#endif
?
JW
PS. I am working on the register definitions...
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thank you all very much for all the help, information, and especially the uPSD33xx.h file. I've been very busy and just now got back to SDCC and was amazed.
Best Regards,
Stephen Blair
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm trying to start out with the Blink_LED code included with Keil compiler. Their sample code works on my target processor and the LEDs blink correctly. Now I'm tring to get it to work with SDCC and am having trouble with the below noted areas:
That did it. It's always the simple things at first.
Now I cannot get the ISR for TIMER0 to fire:
//-------------------------------------------------------------------------
// Blink_LED.c
//
#define PSD_CSIOP 0x7F00
#include <uPSD33XX.h>
#include "upsd3300_timer.h"
/*------------------------------------------------------------------------------
Global Variable Declarations
------------------------------------------------------------------------------*/
static unsigned int idata timer0_tick;
static unsigned int idata timer0_value;
This function is an interrupt service routine for TIMER 0. It should never
be called by a C or assembly function. It will be executed automatically
when TIMER 0 overflows.
This ISR stops timer0, adjusts the counter so that another interrupt occurs in
10ms, and then restarts the timer.
------------------------------------------------------------------------------*/
static void timer0_isr (void) interrupt TIMER0_INTERRUPT using 1
{
TR0 = 0; /* stop timer 0 */
TL0 = (timer0_value & 0x00FF);
TH0 = (timer0_value >> 8);
TR0 = 1; /* start timer 0 */
timer0_tick++; // Increment global var timer_tick (number of 10ms ticks)
}
This function returns the current Timer 0 tick count.
------------------------------------------------------------------------------*/
unsigned int timer0_count (void)
{
unsigned int t;
EA = 0; // disable interrupts to read a non-changing value
t = timer0_tick;
EA = 1; // enable interrupts
return(t);
}
This is a delay function that waits for the specified number of timer 0 ticks to
pass before returning.
count - unsigned int
- the number of timer ticks to wait before returning from function.
------------------------------------------------------------------------------*/
void timer0_delay (unsigned int count)
{
unsigned int start_count;
start_count = timer0_count(); /* get the start count */
while ((timer0_count() - start_count) <= count) /* wait for count "ticks" */
{
PCON |= 0x01; // Idle MCU to wait for timer tick
}
}
//-------------------------------------------------------------------------
I hate to ask for so much assistance but I've got to get over this learning curve.
Best Regards,
Stephen Blair
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This is one of the quirks of SDCC. It needs to see at least the prototype of the ISR's in the file containing main() so it can fill the interrunpt vector tabel. I guess you'll have to remove the static keyword from it too. It's all in the manual.
Maarten
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
My previous post entitled "ST Electronics uPSD Family of Processors" is really meant as a cry for help to add support for the uPSD3354 microprocessor.
Should I create an mcs51reg_update.h file and submitt it?
Thanks,
Stephen Blair
ST also has a user forum. SDCC is mentioned there but corresponding include files have never found their way into SDCC:
http://mcu.st.com/mcu/modules.php?mop=modload&name=Splatt_Forums&file=viewtopic&topic=377&forum=11
(Nowadays an include file which uses the defines within compiler.h would be preferred. F.e. like here:
http://sdcc.svn.sourceforge.net/viewvc/sdcc/trunk/sdcc/device/include/mcs51/ADuC84x.h?revision=4776&view=markup
)
I just added uPSD33xx.h to the subversion repository:
http://svn.sourceforge.net/viewvc/sdcc/trunk/sdcc/device/include/mcs51/uPSD33xx.h?view=log
Please report any errors!
J
> Please report any errors!
Thanks a lot for adding:)
And no error:) Just some strangeness between the
initialization code for the uPSD posted here:
http://sourceforge.net/forum/message.php?msg_id=4293380
and table 16 of the datasheet
"uPSD33xx (Turbo Series) Fast 8032 MCU with Programmable Logic"
9685.pdf available here:
http://www.st.com/stonline/products/literature/ds/9685.htm
The IRQ with the highest priority at 0x63 within table 16
is marked as "reserved" within the data sheet.
YET the initialization code explicitely uses it and warns
about its removal:
; Turbo Debug Interrupt Service routine - Do Not Remove
CSEG AT 063H ; debug interrupt vector
...
Seems some undocumented but nevertheless important
feature is lurking there.
Another topic: maybe add SFR16 definitions for the timers
and the PCA unit (similar to those in C8051F520.h)
for the uPSD as well?
Greetings,
Frieder
What about adding an ISR to the .h file? Something like this:
// Turbo Debug Interrupt Service routine - Do Not Remove
void Turbo_Debug_interrupt(void) interrupt ((0x63-3)/8) _naked
{
_asm
ANL 0xCF,#0xFD ; clear debug interrupt request flag
nop
_endasm;
}
That violates the "no definitions in a header file" paradigm. If the file is included in two source files the linker will generate an error.
If however you only insert the prototype and the header is included in the source containing main, the vector will be generated and the linker will require the ISR to be defined.
I'm not up to speed with "inline" yet, but maybe that can solve this issue.
I noticed there is no P2 and no _XPAGE in the uPSD33xx.h. It seems the uPSD cannot use MOVX @Ri to access anything beyond the first 256 bytes. But it does have dual DPTR's. To make this work you need to adapt crtxclear.asm and crtxinit.asm in the libraries. If you want you can also adapt crtxstack.
Maarten
I am not 100% certain for 33xx, but in 32xx I am sucessfully using MOVX @Ri to access all external code memory with P2 as a higher address.
The documentation in this regard is unfortunately unclear, but in fact, although not connected to external pins, the P2 is present and connected internally to the PSD section as A8-A15.
I would be very surprised if this would be otherwise in 33xx (and for that matter, 34xx, too). After all, these are normal '51s (with some enhancements), connected to the PSD (=FLASH+RAM+GAL in one chip) in a multichip module form.
JW
PS. I'd add at least the offsets to the PSD port registers to the .h, too.
PS. OK, OK, I know. I should do it. Sorry, not today...
The datasheet says otherwise. 0xA0 is RESERVED. And it explicitly mentions it cannot access beyond the first 256 bytes (page 30).
http://www.st.com/stonline/books/pdf/docs/9685.pdf
I looked again and crtclear.asm doesn't need adaptation anymore than crtxstack does, assuming it's ok to write 0x00 to the reserved sfr at 0xA0.
I'll upload a new version of crtxinit.asm later today that conditionally can use dual data pointers instead of movx @Ri. It will not be much smaller or faster either way as it will not use auto-toggle or auto-increment features. And it requires an sfr named DPS to be defined instead of DPTC/AUXR1 with bit 0 as the selector.
Maarten
> The datasheet says otherwise. 0xA0 is RESERVED.
> And it explicitly mentions it cannot access beyond the first 256 bytes (page 30).
Well, then I AM very surprised. :-)
In the afternoon when I wrote that I checked with my uPSD33xx datasheet and P2 WAS there, and - now I looked better and that is a preliminary datasheet from 2003, I never needed a newer one...
I think the difference is beceause of the memory manager built into the 33xx/34xx (prefetch & jump cache).
I still think the .h can be augmented with definitions for the PSD register offsets... Or, even better, declare the registers as variables in XDATA memory, based on a base address for the registers to be passed to the .h - something like:
#ifndef PSD_CSIOP
#define PSD_CSIOP 0x1000 // some arbitrary default value
#endif
xdata at PSD_CSIOP+0xE2 unsigned char PSD_VM;
etc.
and the usage would be
someprogram.c:
#define PSD_CSIOP 0x3000
#include <upsd3xx.h>
Is this a good idea?
JW
Instead of the explicit
xdata at PSD_CSIOP+0xE2 unsigned char PSD_VM;
please use the macro SFRX from compiler.h. That's what it's for.
I assume these registers can be mapped to a variable base address then. Do they actually have a default base or are you required to always set it? If there is no default I would tend to leave out the default value from the header file along with all SFRX definitions. This forces the user to think about what he/she's doing and supply the base. It will generate an error otherwise, unless these xdata registers are not used at all.
Now who volunteers?
Think of it as the registers are chip-selected from a GAL(PLD)-based address decoder, so the base address is determined by having configured (created a "bitstream") for the the GAL(PLD).
So, at the end of the day, the base address is user defined and, yes, (s)he should enter it explicitly. It is very unlikely that somebody would use a uPSD and NOT use any of these registers - at least they are needed to write and read to/from pins other than P1/P3 (i.e. roughly half of the I/O of the chip)...
Is there any standard mechanism to throw an explicit error, possibly explaining the cause of the error to the unaware user? Something like:
#ifndef PLD_CSIOP
#throw_error You should define PLD_CSIOP according to the chip configuration
#endif
?
JW
PS. I am working on the register definitions...
OK I've discovered the #error directive :-)
Please don't laugh too loudly. I still AM a C-hater.
JW
Submitted as patch #1715750 (although it is not a patch :-| )
Next step: uPSD32xx.h and uPSD34xx.h . They should be pretty similar. I am rather tired at the moment...
JW
Added.
Thank you all very much for all the help, information, and especially the uPSD33xx.h file. I've been very busy and just now got back to SDCC and was amazed.
Best Regards,
Stephen Blair
I'm trying to start out with the Blink_LED code included with Keil compiler. Their sample code works on my target processor and the LEDs blink correctly. Now I'm tring to get it to work with SDCC and am having trouble with the below noted areas:
#define PSD_CSIOP 0x7F00
#include <uPSD33XX.h>
#include "upsd3300_timer.h"
#define LED1_ON_LED2_ON 0xF9
#define LED1_OFF_LED2_OFF 0xFF
#define LED1_ON_LED2_OFF 0xFB
#define LED1_OFF_LED2_ON 0xFD
#define LONG 100
#define MEDDIUM 50
#define SHORT 10
#define YES 1
#define NO 0
//xdata volatile PSD_REGS PSD_reg _at_ PSD_CSIOP; // Cannot find reference to PSD_REGS in Keil, so needless to say there isn't on in SDCC
void main(void)
{
static char blink_delay, blink_leds_together;
blink_delay = LONG;
blink_leds_together = NO;
timer0_init();
// PSD_PSD_reg.PMMR0|=0x08; // Use PSD.reg or...
PSD_CSIOP.PMMR2|=0x3C; // PSD_CSIOP ? Neither works.
PSD_CSIOP.DIRECTION_D|=0x06;
PSD_CSIOP.DATAOUT_D = LED1_OFF_LED2_OFF;
While (1)
{
if(blink_leds_together == YES)
PSD_CSIOP.DATAOUT_D = LED1_ON_LED2_ON;
else
PSD_CSIOP.DATAOUT_D = LED1_ON_LED2_OFF;
timer0_delay(blink_delay);
if(blink_leds_together == YES)
PSD_CSIOP.DATAOUT_D = LED1_OFF_LED2_OFF;
else
PSD_CSIOP.DATAOUT_D = LED1_OFF_LED2_ON;
timer0_delay(blink_delay);
}
}
Any Help would be greatly appreciated.
Best Regards,
Stephen Blair
Please check the file "uPSD33XX.h" for the register names. For example, instead of using:
PSD_CSIOP.PMMR0|=0x08;
PSD_CSIOP.PMMR2|=0x3C;
PSD_CSIOP.DIRECTION_D|=0x06;
PSD_CSIOP.DATAOUT_D = LED1_OFF_LED2_OFF;
you should use:
PSD_PMMR0|=0x08;
PSD_PMMR2|=0x3C;
PSD_DIRECTION_D|=0x06;
PSD_DATAOUT_D = LED1_OFF_LED2_OFF;
and such.
That did it. It's always the simple things at first.
Now I cannot get the ISR for TIMER0 to fire:
//-------------------------------------------------------------------------
// Blink_LED.c
//
#define PSD_CSIOP 0x7F00
#include <uPSD33XX.h>
#include "upsd3300_timer.h"
#define LED1_ON_LED2_ON 0xF9
#define LED1_OFF_LED2_OFF 0xFF
#define LED1_ON_LED2_OFF 0xFB
#define LED1_OFF_LED2_ON 0xFD
#define LONG 100
#define MEDDIUM 50
#define SHORT 10
#define YES 1
#define NO 0
main()
{
static char blink_delay, blink_leds_together, use_timer0;
static long x, y;
blink_delay = LONG;
blink_leds_together = NO;
use_timer0 = YES;
if(use_timer0 == YES)
timer0_init();
PSD_PMMR0|=0x08;
PSD_PMMR2|=0x3C;
PSD_DIRECTION_D|=0x06;
PSD_DATAOUT_D = LED1_OFF_LED2_OFF;
while (1)
{
if(blink_leds_together == YES)
PSD_DATAOUT_D = LED1_ON_LED2_ON;
else
PSD_DATAOUT_D = LED1_ON_LED2_OFF;
if(use_timer0 == YES)
timer0_delay(blink_delay);
else
{
y=0;
for(x=0; x<10000L; x=x+1)
{
y=y+1;
}
}
if(blink_leds_together == YES)
PSD_DATAOUT_D = LED1_OFF_LED2_OFF;
else
PSD_DATAOUT_D = LED1_OFF_LED2_ON;
if(use_timer0 == YES)
timer0_delay(blink_delay);
else
{
y=0;
for(x=0; x<10000L; x=x+1)
{
y=y+1;
}
}
}
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
// upsd3300_timer.c
//
#define PSD_CSIOP 0x7F00
#include "upsd33XX.h"
#include "upsd3300_timer.h"
/*------------------------------------------------------------------------------
Global Variable Declarations
------------------------------------------------------------------------------*/
static unsigned int idata timer0_tick;
static unsigned int idata timer0_value;
#define FREQ_OSC 40000
/*------------------------------------------------------------------------------
timer0_isr()
This function is an interrupt service routine for TIMER 0. It should never
be called by a C or assembly function. It will be executed automatically
when TIMER 0 overflows.
This ISR stops timer0, adjusts the counter so that another interrupt occurs in
10ms, and then restarts the timer.
------------------------------------------------------------------------------*/
static void timer0_isr (void) interrupt TIMER0_INTERRUPT using 1
{
TR0 = 0; /* stop timer 0 */
TL0 = (timer0_value & 0x00FF);
TH0 = (timer0_value >> 8);
TR0 = 1; /* start timer 0 */
timer0_tick++; // Increment global var timer_tick (number of 10ms ticks)
}
/*------------------------------------------------------------------------------
timer0_init();
This function enables TIMER 0. TIMER 0 will generate a synchronous interrupt
once every 100Hz (10ms).
------------------------------------------------------------------------------*/
void timer0_init (void)
{
EA = 0; /* disable interrupts */
timer0_tick = 0;
TR0 = 0; /* stop timer 0 */
TMOD &= 0xF0; /* clear timer 0 mode bits - bottom 4 bits */
TMOD |= 0x01; /* put timer 0 into 16-bit no prescale */
// Calculate timer rollover based on FREQ_OSC to be 10ms periods (100hz)
timer0_value = 0x10000 - ( ((FREQ_OSC * 5L) / 6L) - 17L);
TL0 = (timer0_value & 0x00FF);
TH0 = (timer0_value >> 8);
PT0 = 1; /* set high priority interrupt for timer 0 */
ET0 = 1; /* enable timer 0 interrupt */
TR0 = 1; /* start timer 0 */
EA = 1; /* enable interrupts */
}
/*------------------------------------------------------------------------------
timer0_count ();
This function returns the current Timer 0 tick count.
------------------------------------------------------------------------------*/
unsigned int timer0_count (void)
{
unsigned int t;
EA = 0; // disable interrupts to read a non-changing value
t = timer0_tick;
EA = 1; // enable interrupts
return(t);
}
/*------------------------------------------------------------------------------
timer0_delay (count);
This is a delay function that waits for the specified number of timer 0 ticks to
pass before returning.
count - unsigned int
- the number of timer ticks to wait before returning from function.
------------------------------------------------------------------------------*/
void timer0_delay (unsigned int count)
{
unsigned int start_count;
start_count = timer0_count(); /* get the start count */
while ((timer0_count() - start_count) <= count) /* wait for count "ticks" */
{
PCON |= 0x01; // Idle MCU to wait for timer tick
}
}
//-------------------------------------------------------------------------
I hate to ask for so much assistance but I've got to get over this learning curve.
Best Regards,
Stephen Blair
Stephen,
This is one of the quirks of SDCC. It needs to see at least the prototype of the ISR's in the file containing main() so it can fill the interrunpt vector tabel. I guess you'll have to remove the static keyword from it too. It's all in the manual.
Maarten